changeset 1458:e0b2d67cfe7c

Added druntime (this should be removed once it works).
author Robert Clipsham <robert@octarineparrot.com>
date Tue, 02 Jun 2009 17:43:06 +0100
parents 7b218ec1044f
children 69a195e07d89
files .hgignore druntime/import/core/bitmanip.di druntime/import/core/stdc/complex.d druntime/import/core/stdc/config.d druntime/import/core/stdc/ctype.d druntime/import/core/stdc/errno.d druntime/import/core/stdc/fenv.d druntime/import/core/stdc/float_.d druntime/import/core/stdc/inttypes.d druntime/import/core/stdc/limits.d druntime/import/core/stdc/locale.d druntime/import/core/stdc/math.d druntime/import/core/stdc/signal.d druntime/import/core/stdc/stdarg.d druntime/import/core/stdc/stddef.d druntime/import/core/stdc/stdint.d druntime/import/core/stdc/stdio.d druntime/import/core/stdc/stdlib.d druntime/import/core/stdc/string.d druntime/import/core/stdc/tgmath.d druntime/import/core/stdc/time.d druntime/import/core/stdc/wchar_.d druntime/import/core/stdc/wctype.d druntime/import/core/sys/osx/mach/kern_return.d druntime/import/core/sys/osx/mach/port.d druntime/import/core/sys/osx/mach/semaphore.d druntime/import/core/sys/osx/mach/thread_act.d druntime/import/core/sys/posix/arpa/inet.d druntime/import/core/sys/posix/config.d druntime/import/core/sys/posix/dirent.d druntime/import/core/sys/posix/dlfcn.d druntime/import/core/sys/posix/fcntl.d druntime/import/core/sys/posix/inttypes.d druntime/import/core/sys/posix/net/if_.d druntime/import/core/sys/posix/netinet/in_.d druntime/import/core/sys/posix/netinet/tcp.d druntime/import/core/sys/posix/poll.d druntime/import/core/sys/posix/pthread.d druntime/import/core/sys/posix/pwd.d druntime/import/core/sys/posix/sched.d druntime/import/core/sys/posix/semaphore.d druntime/import/core/sys/posix/setjmp.d druntime/import/core/sys/posix/signal.d druntime/import/core/sys/posix/stdio.d druntime/import/core/sys/posix/stdlib.d druntime/import/core/sys/posix/sys/ipc.d druntime/import/core/sys/posix/sys/mman.d druntime/import/core/sys/posix/sys/select.d druntime/import/core/sys/posix/sys/shm.d druntime/import/core/sys/posix/sys/socket.d druntime/import/core/sys/posix/sys/stat.d druntime/import/core/sys/posix/sys/time.d druntime/import/core/sys/posix/sys/types.d druntime/import/core/sys/posix/sys/uio.d druntime/import/core/sys/posix/sys/wait.d druntime/import/core/sys/posix/termios.d druntime/import/core/sys/posix/time.d druntime/import/core/sys/posix/ucontext.d druntime/import/core/sys/posix/unistd.d druntime/import/core/sys/posix/utime.d druntime/import/core/sys/windows/windows.d druntime/import/object.di druntime/import/std/c/stdarg.di druntime/import/std/intrinsic.di druntime/import/std/stdarg.di druntime/src/build-dmd.bat druntime/src/build-dmd.sh druntime/src/build-ldc.sh druntime/src/common/core/bitmanip.d druntime/src/common/core/bitop.d druntime/src/common/core/exception.d druntime/src/common/core/memory.d druntime/src/common/core/runtime.d druntime/src/common/core/stdc/errno.c druntime/src/common/core/sync/barrier.d druntime/src/common/core/sync/condition.d druntime/src/common/core/sync/config.d druntime/src/common/core/sync/exception.d druntime/src/common/core/sync/mutex.d druntime/src/common/core/sync/rwmutex.d druntime/src/common/core/sync/semaphore.d druntime/src/common/core/thread.d druntime/src/common/core/threadasm.S druntime/src/common/core/vararg.d druntime/src/common/posix.mak druntime/src/common/win32.mak druntime/src/compiler/dmd/aApply.d druntime/src/compiler/dmd/aApplyR.d druntime/src/compiler/dmd/aaA.d druntime/src/compiler/dmd/adi.d druntime/src/compiler/dmd/alloca.d druntime/src/compiler/dmd/arrayassign.d druntime/src/compiler/dmd/arraybyte.d druntime/src/compiler/dmd/arraycast.d druntime/src/compiler/dmd/arraycat.d druntime/src/compiler/dmd/arraydouble.d druntime/src/compiler/dmd/arrayfloat.d druntime/src/compiler/dmd/arrayint.d druntime/src/compiler/dmd/arrayreal.d druntime/src/compiler/dmd/arrayshort.d druntime/src/compiler/dmd/cast_.d druntime/src/compiler/dmd/cmath2.d druntime/src/compiler/dmd/compiler.d druntime/src/compiler/dmd/complex.c druntime/src/compiler/dmd/cover.d druntime/src/compiler/dmd/critical.c druntime/src/compiler/dmd/deh.c druntime/src/compiler/dmd/deh2.d druntime/src/compiler/dmd/dmain2.BAK druntime/src/compiler/dmd/dmain2.d druntime/src/compiler/dmd/invariant.d druntime/src/compiler/dmd/invariant_.d druntime/src/compiler/dmd/lifetime.d druntime/src/compiler/dmd/llmath.d druntime/src/compiler/dmd/mars.h druntime/src/compiler/dmd/memory.d druntime/src/compiler/dmd/memory_osx.c druntime/src/compiler/dmd/memset.d druntime/src/compiler/dmd/minit.asm druntime/src/compiler/dmd/monitor.c druntime/src/compiler/dmd/obj.d druntime/src/compiler/dmd/object_.d druntime/src/compiler/dmd/posix.mak druntime/src/compiler/dmd/qsort.d druntime/src/compiler/dmd/qsort2.d druntime/src/compiler/dmd/switch_.d druntime/src/compiler/dmd/tls.S druntime/src/compiler/dmd/trace.d druntime/src/compiler/dmd/typeinfo/ti_AC.d druntime/src/compiler/dmd/typeinfo/ti_Acdouble.d druntime/src/compiler/dmd/typeinfo/ti_Acfloat.d druntime/src/compiler/dmd/typeinfo/ti_Acreal.d druntime/src/compiler/dmd/typeinfo/ti_Adouble.d druntime/src/compiler/dmd/typeinfo/ti_Afloat.d druntime/src/compiler/dmd/typeinfo/ti_Ag.d druntime/src/compiler/dmd/typeinfo/ti_Aint.d druntime/src/compiler/dmd/typeinfo/ti_Along.d druntime/src/compiler/dmd/typeinfo/ti_Areal.d druntime/src/compiler/dmd/typeinfo/ti_Ashort.d druntime/src/compiler/dmd/typeinfo/ti_C.d druntime/src/compiler/dmd/typeinfo/ti_byte.d druntime/src/compiler/dmd/typeinfo/ti_cdouble.d druntime/src/compiler/dmd/typeinfo/ti_cfloat.d druntime/src/compiler/dmd/typeinfo/ti_char.d druntime/src/compiler/dmd/typeinfo/ti_creal.d druntime/src/compiler/dmd/typeinfo/ti_dchar.d druntime/src/compiler/dmd/typeinfo/ti_delegate.d druntime/src/compiler/dmd/typeinfo/ti_double.d druntime/src/compiler/dmd/typeinfo/ti_float.d druntime/src/compiler/dmd/typeinfo/ti_idouble.d druntime/src/compiler/dmd/typeinfo/ti_ifloat.d druntime/src/compiler/dmd/typeinfo/ti_int.d druntime/src/compiler/dmd/typeinfo/ti_ireal.d druntime/src/compiler/dmd/typeinfo/ti_long.d druntime/src/compiler/dmd/typeinfo/ti_ptr.d druntime/src/compiler/dmd/typeinfo/ti_real.d druntime/src/compiler/dmd/typeinfo/ti_short.d druntime/src/compiler/dmd/typeinfo/ti_ubyte.d druntime/src/compiler/dmd/typeinfo/ti_uint.d druntime/src/compiler/dmd/typeinfo/ti_ulong.d druntime/src/compiler/dmd/typeinfo/ti_ushort.d druntime/src/compiler/dmd/typeinfo/ti_void.d druntime/src/compiler/dmd/typeinfo/ti_wchar.d druntime/src/compiler/dmd/util/console.d druntime/src/compiler/dmd/util/cpuid.d druntime/src/compiler/dmd/util/ctype.d druntime/src/compiler/dmd/util/string.d druntime/src/compiler/dmd/util/utf.d druntime/src/compiler/dmd/win32.mak druntime/src/compiler/ldc/aApply.d druntime/src/compiler/ldc/aApplyR.d druntime/src/compiler/ldc/aaA.d druntime/src/compiler/ldc/adi.d druntime/src/compiler/ldc/alloca.d druntime/src/compiler/ldc/arrayassign.d druntime/src/compiler/ldc/arraybyte.d druntime/src/compiler/ldc/arraycast.d druntime/src/compiler/ldc/arraycat.d druntime/src/compiler/ldc/arraydouble.d druntime/src/compiler/ldc/arrayfloat.d druntime/src/compiler/ldc/arrayint.d druntime/src/compiler/ldc/arrayreal.d druntime/src/compiler/ldc/arrayshort.d druntime/src/compiler/ldc/cast_.d druntime/src/compiler/ldc/cmath2.d druntime/src/compiler/ldc/compiler.d druntime/src/compiler/ldc/complex.c druntime/src/compiler/ldc/cover.d druntime/src/compiler/ldc/critical.c druntime/src/compiler/ldc/deh.c druntime/src/compiler/ldc/deh2.d druntime/src/compiler/ldc/dmain2.BAK druntime/src/compiler/ldc/dmain2.d druntime/src/compiler/ldc/genobj.d druntime/src/compiler/ldc/invariant.d druntime/src/compiler/ldc/invariant_.d druntime/src/compiler/ldc/lifetime.d druntime/src/compiler/ldc/llmath.d druntime/src/compiler/ldc/mars.h druntime/src/compiler/ldc/memory.d druntime/src/compiler/ldc/memory_osx.c druntime/src/compiler/ldc/memset.d druntime/src/compiler/ldc/minit.asm druntime/src/compiler/ldc/monitor.c druntime/src/compiler/ldc/obj.d druntime/src/compiler/ldc/posix.mak druntime/src/compiler/ldc/qsort.d druntime/src/compiler/ldc/qsort2.d druntime/src/compiler/ldc/switch_.d druntime/src/compiler/ldc/tls.S druntime/src/compiler/ldc/trace.d druntime/src/compiler/ldc/typeinfo/ti_AC.d druntime/src/compiler/ldc/typeinfo/ti_Acdouble.d druntime/src/compiler/ldc/typeinfo/ti_Acfloat.d druntime/src/compiler/ldc/typeinfo/ti_Acreal.d druntime/src/compiler/ldc/typeinfo/ti_Adouble.d druntime/src/compiler/ldc/typeinfo/ti_Afloat.d druntime/src/compiler/ldc/typeinfo/ti_Ag.d druntime/src/compiler/ldc/typeinfo/ti_Aint.d druntime/src/compiler/ldc/typeinfo/ti_Along.d druntime/src/compiler/ldc/typeinfo/ti_Areal.d druntime/src/compiler/ldc/typeinfo/ti_Ashort.d druntime/src/compiler/ldc/typeinfo/ti_C.d druntime/src/compiler/ldc/typeinfo/ti_byte.d druntime/src/compiler/ldc/typeinfo/ti_cdouble.d druntime/src/compiler/ldc/typeinfo/ti_cfloat.d druntime/src/compiler/ldc/typeinfo/ti_char.d druntime/src/compiler/ldc/typeinfo/ti_creal.d druntime/src/compiler/ldc/typeinfo/ti_dchar.d druntime/src/compiler/ldc/typeinfo/ti_delegate.d druntime/src/compiler/ldc/typeinfo/ti_double.d druntime/src/compiler/ldc/typeinfo/ti_float.d druntime/src/compiler/ldc/typeinfo/ti_idouble.d druntime/src/compiler/ldc/typeinfo/ti_ifloat.d druntime/src/compiler/ldc/typeinfo/ti_int.d druntime/src/compiler/ldc/typeinfo/ti_ireal.d druntime/src/compiler/ldc/typeinfo/ti_long.d druntime/src/compiler/ldc/typeinfo/ti_ptr.d druntime/src/compiler/ldc/typeinfo/ti_real.d druntime/src/compiler/ldc/typeinfo/ti_short.d druntime/src/compiler/ldc/typeinfo/ti_ubyte.d druntime/src/compiler/ldc/typeinfo/ti_uint.d druntime/src/compiler/ldc/typeinfo/ti_ulong.d druntime/src/compiler/ldc/typeinfo/ti_ushort.d druntime/src/compiler/ldc/typeinfo/ti_void.d druntime/src/compiler/ldc/typeinfo/ti_wchar.d druntime/src/compiler/ldc/util/console.d druntime/src/compiler/ldc/util/cpuid.d druntime/src/compiler/ldc/util/ctype.d druntime/src/compiler/ldc/util/string.d druntime/src/compiler/ldc/util/utf.d druntime/src/compiler/ldc/win32.mak druntime/src/dmd-posix.mak druntime/src/dmd-win32.mak druntime/src/dmd.conf druntime/src/gc/basic/gc.d druntime/src/gc/basic/gcalloc.d druntime/src/gc/basic/gcbits.d druntime/src/gc/basic/gcstats.d druntime/src/gc/basic/gcx.d druntime/src/gc/basic/posix.mak druntime/src/gc/basic/win32.mak druntime/src/gc/stub/gc.d druntime/src/gc/stub/posix.mak druntime/src/gc/stub/win32.mak druntime/src/ldc-posix-tango.mak druntime/src/ldc-posix.mak druntime/src/sc.ini druntime/src/test-dmd.sh
diffstat 269 files changed, 83741 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Tue Jun 02 17:12:37 2009 +0100
+++ b/.hgignore	Tue Jun 02 17:43:06 2009 +0100
@@ -21,7 +21,6 @@
 ^tests/dstress/
 ^tests/reference/
 ^tango/
-^druntime/
 ^import/
 ^bin/ldc2?$
 ^bin/ldc2?\.conf$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/bitmanip.di	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,262 @@
+/**
+ * This module contains a collection of bit-level operations.
+ *
+ * Copyright: Copyright (c) 2005-2008, The D Runtime Project
+ * License:   BSD Style, see LICENSE
+ * Authors:   Walter Bright, Don Clugston, Sean Kelly
+ */
+module core.bitmanip;
+
+
+version( DDoc )
+{
+    /**
+     * Scans the bits in v starting with bit 0, looking
+     * for the first set bit.
+     * Returns:
+     *  The bit number of the first bit set.
+     *  The return value is undefined if v is zero.
+     */
+    int bsf( uint v );
+
+
+    /**
+     * Scans the bits in v from the most significant bit
+     * to the least significant bit, looking
+     * for the first set bit.
+     * Returns:
+     *  The bit number of the first bit set.
+     *  The return value is undefined if v is zero.
+     * Example:
+     * ---
+     * import bitmanip;
+     *
+     * int main()
+     * {
+     *     uint v;
+     *     int x;
+     *
+     *     v = 0x21;
+     *     x = bsf(v);
+     *     printf("bsf(x%x) = %d\n", v, x);
+     *     x = bsr(v);
+     *     printf("bsr(x%x) = %d\n", v, x);
+     *     return 0;
+     * }
+     * ---
+     * Output:
+     *  bsf(x21) = 0<br>
+     *  bsr(x21) = 5
+     */
+    int bsr( uint v );
+
+
+    /**
+     * Tests the bit.
+     */
+    int bt( uint* p, uint bitnum );
+
+
+    /**
+     * Tests and complements the bit.
+     */
+    int btc( uint* p, uint bitnum );
+
+
+    /**
+     * Tests and resets (sets to 0) the bit.
+     */
+    int btr( uint* p, uint bitnum );
+
+
+    /**
+     * Tests and sets the bit.
+     * Params:
+     * p = a non-NULL pointer to an array of uints.
+     * index = a bit number, starting with bit 0 of p[0],
+     * and progressing. It addresses bits like the expression:
+    ---
+    p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)))
+    ---
+     * Returns:
+     *  A non-zero value if the bit was set, and a zero
+     *  if it was clear.
+     *
+     * Example:
+     * ---
+    import bitmanip;
+
+    int main()
+    {
+        uint array[2];
+
+        array[0] = 2;
+        array[1] = 0x100;
+
+        printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("bts(array, 35) = %d\n", <b>bts</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("btr(array, 35) = %d\n", <b>btr</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("bt(array, 1) = %d\n", <b>bt</b>(array, 1));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        return 0;
+    }
+     * ---
+     * Output:
+    <pre>
+    btc(array, 35) = 0
+    array = [0]:x2, [1]:x108
+    btc(array, 35) = -1
+    array = [0]:x2, [1]:x100
+    bts(array, 35) = 0
+    array = [0]:x2, [1]:x108
+    btr(array, 35) = -1
+    array = [0]:x2, [1]:x100
+    bt(array, 1) = -1
+    array = [0]:x2, [1]:x100
+    </pre>
+     */
+    int bts( uint* p, uint bitnum );
+
+
+    /**
+     * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes
+     * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3
+     * becomes byte 0.
+     */
+    uint bswap( uint v );
+
+
+    /**
+     * Reads I/O port at port_address.
+     */
+    ubyte inp( uint port_address );
+
+
+    /**
+     * ditto
+     */
+    ushort inpw( uint port_address );
+
+
+    /**
+     * ditto
+     */
+    uint inpl( uint port_address );
+
+
+    /**
+     * Writes and returns value to I/O port at port_address.
+     */
+    ubyte outp( uint port_address, ubyte value );
+
+
+    /**
+     * ditto
+     */
+    ushort outpw( uint port_address, ushort value );
+
+
+    /**
+     * ditto
+     */
+    uint outpl( uint port_address, uint value );
+}
+else
+{
+    public import std.intrinsic;
+}
+
+
+/**
+ *  Calculates the number of set bits in a 32-bit integer.
+ */
+int popcnt( uint x )
+{
+    // Avoid branches, and the potential for cache misses which
+    // could be incurred with a table lookup.
+
+    // We need to mask alternate bits to prevent the
+    // sum from overflowing.
+    // add neighbouring bits. Each bit is 0 or 1.
+    x = x - ((x>>1) & 0x5555_5555);
+    // now each two bits of x is a number 00,01 or 10.
+    // now add neighbouring pairs
+    x = ((x&0xCCCC_CCCC)>>2) + (x&0x3333_3333);
+    // now each nibble holds 0000-0100. Adding them won't
+    // overflow any more, so we don't need to mask any more
+
+    // Now add the nibbles, then the bytes, then the words
+    // We still need to mask to prevent double-counting.
+    // Note that if we used a rotate instead of a shift, we
+    // wouldn't need the masks, and could just divide the sum
+    // by 8 to account for the double-counting.
+    // On some CPUs, it may be faster to perform a multiply.
+
+    x += (x>>4);
+    x &= 0x0F0F_0F0F;
+    x += (x>>8);
+    x &= 0x00FF_00FF;
+    x += (x>>16);
+    x &= 0xFFFF;
+    return x;
+}
+
+
+/**
+ * Reverses the order of bits in a 32-bit integer.
+ */
+uint bitswap( uint x )
+{
+
+    version( D_InlineAsm_X86 )
+    {
+        asm
+        {
+            // Author: Tiago Gasiba.
+            mov EDX, EAX;
+            shr EAX, 1;
+            and EDX, 0x5555_5555;
+            and EAX, 0x5555_5555;
+            shl EDX, 1;
+            or  EAX, EDX;
+            mov EDX, EAX;
+            shr EAX, 2;
+            and EDX, 0x3333_3333;
+            and EAX, 0x3333_3333;
+            shl EDX, 2;
+            or  EAX, EDX;
+            mov EDX, EAX;
+            shr EAX, 4;
+            and EDX, 0x0f0f_0f0f;
+            and EAX, 0x0f0f_0f0f;
+            shl EDX, 4;
+            or  EAX, EDX;
+            bswap EAX;
+        }
+    }
+    else
+    {
+        // swap odd and even bits
+        x = ((x >> 1) & 0x5555_5555) | ((x & 0x5555_5555) << 1);
+        // swap consecutive pairs
+        x = ((x >> 2) & 0x3333_3333) | ((x & 0x3333_3333) << 2);
+        // swap nibbles
+        x = ((x >> 4) & 0x0F0F_0F0F) | ((x & 0x0F0F_0F0F) << 4);
+        // swap bytes
+        x = ((x >> 8) & 0x00FF_00FF) | ((x & 0x00FF_00FF) << 8);
+        // swap 2-byte long pairs
+        x = ( x >> 16              ) | ( x               << 16);
+        return x;
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/complex.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,107 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.complex;
+
+extern (C):
+
+alias creal complex;
+alias ireal imaginary;
+
+cdouble cacos(cdouble z);
+cfloat  cacosf(cfloat z);
+creal   cacosl(creal z);
+
+cdouble casin(cdouble z);
+cfloat  casinf(cfloat z);
+creal   casinl(creal z);
+
+cdouble catan(cdouble z);
+cfloat  catanf(cfloat z);
+creal   catanl(creal z);
+
+cdouble ccos(cdouble z);
+cfloat  ccosf(cfloat z);
+creal   ccosl(creal z);
+
+cdouble csin(cdouble z);
+cfloat  csinf(cfloat z);
+creal   csinl(creal z);
+
+cdouble ctan(cdouble z);
+cfloat  ctanf(cfloat z);
+creal   ctanl(creal z);
+
+cdouble cacosh(cdouble z);
+cfloat  cacoshf(cfloat z);
+creal   cacoshl(creal z);
+
+cdouble casinh(cdouble z);
+cfloat  casinhf(cfloat z);
+creal   casinhl(creal z);
+
+cdouble catanh(cdouble z);
+cfloat  catanhf(cfloat z);
+creal   catanhl(creal z);
+
+cdouble ccosh(cdouble z);
+cfloat  ccoshf(cfloat z);
+creal   ccoshl(creal z);
+
+cdouble csinh(cdouble z);
+cfloat  csinhf(cfloat z);
+creal   csinhl(creal z);
+
+cdouble ctanh(cdouble z);
+cfloat  ctanhf(cfloat z);
+creal   ctanhl(creal z);
+
+cdouble cexp(cdouble z);
+cfloat  cexpf(cfloat z);
+creal   cexpl(creal z);
+
+cdouble clog(cdouble z);
+cfloat  clogf(cfloat z);
+creal   clogl(creal z);
+
+ double cabs(cdouble z);
+ float  cabsf(cfloat z);
+ real   cabsl(creal z);
+
+cdouble cpow(cdouble x, cdouble y);
+cfloat  cpowf(cfloat x, cfloat y);
+creal   cpowl(creal x, creal y);
+
+cdouble csqrt(cdouble z);
+cfloat  csqrtf(cfloat z);
+creal   csqrtl(creal z);
+
+ double carg(cdouble z);
+ float  cargf(cfloat z);
+ real   cargl(creal z);
+
+ double cimag(cdouble z);
+ float  cimagf(cfloat z);
+ real   cimagl(creal z);
+
+cdouble conj(cdouble z);
+cfloat  conjf(cfloat z);
+creal   conjl(creal z);
+
+cdouble cproj(cdouble z);
+cfloat  cprojf(cfloat z);
+creal   cprojl(creal z);
+
+// double creal(cdouble z);
+ float  crealf(cfloat z);
+ real   creall(creal z);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/config.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,35 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.config;
+
+extern (C):
+
+version( Windows )
+{
+    alias int   c_long;
+    alias uint  c_ulong;
+}
+else
+{
+  static if( (void*).sizeof > int.sizeof )
+  {
+    alias long  c_long;
+    alias ulong c_ulong;
+  }
+  else
+  {
+    alias int   c_long;
+    alias uint  c_ulong;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/ctype.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,31 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.ctype;
+
+extern (C):
+
+int isalnum(int c);
+int isalpha(int c);
+int isblank(int c);
+int iscntrl(int c);
+int isdigit(int c);
+int isgraph(int c);
+int islower(int c);
+int isprint(int c);
+int ispunct(int c);
+int isspace(int c);
+int isupper(int c);
+int isxdigit(int c);
+int tolower(int c);
+int toupper(int c);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/errno.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,377 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.errno;
+
+extern (C) int getErrno();      // for internal use
+extern (C) int setErrno(int);   // for internal use
+
+alias getErrno errno;
+alias setErrno errno;
+
+extern (C):
+
+version( Windows )
+{
+    enum EPERM              = 1;        // Operation not permitted
+    enum ENOENT             = 2;        // No such file or directory
+    enum ESRCH              = 3;        // No such process
+    enum EINTR              = 4;        // Interrupted system call
+    enum EIO                = 5;        // I/O error
+    enum ENXIO              = 6;        // No such device or address
+    enum E2BIG              = 7;        // Argument list too long
+    enum ENOEXEC            = 8;        // Exec format error
+    enum EBADF              = 9;        // Bad file number
+    enum ECHILD             = 10;       // No child processes
+    enum EAGAIN             = 11;       // Try again
+    enum ENOMEM             = 12;       // Out of memory
+    enum EACCES             = 13;       // Permission denied
+    enum EFAULT             = 14;       // Bad address
+    enum EBUSY              = 16;       // Device or resource busy
+    enum EEXIST             = 17;       // File exists
+    enum EXDEV              = 18;       // Cross-device link
+    enum ENODEV             = 19;       // No such device
+    enum ENOTDIR            = 20;       // Not a directory
+    enum EISDIR             = 21;       // Is a directory
+    enum EINVAL             = 22;       // Invalid argument
+    enum ENFILE             = 23;       // File table overflow
+    enum EMFILE             = 24;       // Too many open files
+    enum ENOTTY             = 25;       // Not a typewriter
+    enum EFBIG              = 27;       // File too large
+    enum ENOSPC             = 28;       // No space left on device
+    enum ESPIPE             = 29;       // Illegal seek
+    enum EROFS              = 30;       // Read-only file system
+    enum EMLINK             = 31;       // Too many links
+    enum EPIPE              = 32;       // Broken pipe
+    enum EDOM               = 33;       // Math argument out of domain of func
+    enum ERANGE             = 34;       // Math result not representable
+    enum EDEADLK            = 36;       // Resource deadlock would occur
+    enum ENAMETOOLONG       = 38;       // File name too long
+    enum ENOLCK             = 39;       // No record locks available
+    enum ENOSYS             = 40;       // Function not implemented
+    enum ENOTEMPTY          = 41;       // Directory not empty
+    enum EILSEQ             = 42;       // Illegal byte sequence
+    enum EDEADLOCK          = EDEADLK;
+}
+else version( linux )
+{
+    enum EPERM              = 1;        // Operation not permitted
+    enum ENOENT             = 2;        // No such file or directory
+    enum ESRCH              = 3;        // No such process
+    enum EINTR              = 4;        // Interrupted system call
+    enum EIO                = 5;        // I/O error
+    enum ENXIO              = 6;        // No such device or address
+    enum E2BIG              = 7;        // Argument list too long
+    enum ENOEXEC            = 8;        // Exec format error
+    enum EBADF              = 9;        // Bad file number
+    enum ECHILD             = 10;       // No child processes
+    enum EAGAIN             = 11;       // Try again
+    enum ENOMEM             = 12;       // Out of memory
+    enum EACCES             = 13;       // Permission denied
+    enum EFAULT             = 14;       // Bad address
+    enum ENOTBLK            = 15;       // Block device required
+    enum EBUSY              = 16;       // Device or resource busy
+    enum EEXIST             = 17;       // File exists
+    enum EXDEV              = 18;       // Cross-device link
+    enum ENODEV             = 19;       // No such device
+    enum ENOTDIR            = 20;       // Not a directory
+    enum EISDIR             = 21;       // Is a directory
+    enum EINVAL             = 22;       // Invalid argument
+    enum ENFILE             = 23;       // File table overflow
+    enum EMFILE             = 24;       // Too many open files
+    enum ENOTTY             = 25;       // Not a typewriter
+    enum ETXTBSY            = 26;       // Text file busy
+    enum EFBIG              = 27;       // File too large
+    enum ENOSPC             = 28;       // No space left on device
+    enum ESPIPE             = 29;       // Illegal seek
+    enum EROFS              = 30;       // Read-only file system
+    enum EMLINK             = 31;       // Too many links
+    enum EPIPE              = 32;       // Broken pipe
+    enum EDOM               = 33;       // Math argument out of domain of func
+    enum ERANGE             = 34;       // Math result not representable
+    enum EDEADLK            = 35;       // Resource deadlock would occur
+    enum ENAMETOOLONG       = 36;       // File name too long
+    enum ENOLCK             = 37;       // No record locks available
+    enum ENOSYS             = 38;       // Function not implemented
+    enum ENOTEMPTY          = 39;       // Directory not empty
+    enum ELOOP              = 40;       // Too many symbolic links encountered
+    enum EWOULDBLOCK        = EAGAIN;   // Operation would block
+    enum ENOMSG             = 42;       // No message of desired type
+    enum EIDRM              = 43;       // Identifier removed
+    enum ECHRNG             = 44;       // Channel number out of range
+    enum EL2NSYNC           = 45;       // Level 2 not synchronized
+    enum EL3HLT             = 46;       // Level 3 halted
+    enum EL3RST             = 47;       // Level 3 reset
+    enum ELNRNG             = 48;       // Link number out of range
+    enum EUNATCH            = 49;       // Protocol driver not attached
+    enum ENOCSI             = 50;       // No CSI structure available
+    enum EL2HLT             = 51;       // Level 2 halted
+    enum EBADE              = 52;       // Invalid exchange
+    enum EBADR              = 53;       // Invalid request descriptor
+    enum EXFULL             = 54;       // Exchange full
+    enum ENOANO             = 55;       // No anode
+    enum EBADRQC            = 56;       // Invalid request code
+    enum EBADSLT            = 57;       // Invalid slot
+    enum EDEADLOCK          = EDEADLK;
+    enum EBFONT             = 59;       // Bad font file format
+    enum ENOSTR             = 60;       // Device not a stream
+    enum ENODATA            = 61;       // No data available
+    enum ETIME              = 62;       // Timer expired
+    enum ENOSR              = 63;       // Out of streams resources
+    enum ENONET             = 64;       // Machine is not on the network
+    enum ENOPKG             = 65;       // Package not installed
+    enum EREMOTE            = 66;       // Object is remote
+    enum ENOLINK            = 67;       // Link has been severed
+    enum EADV               = 68;       // Advertise error
+    enum ESRMNT             = 69;       // Srmount error
+    enum ECOMM              = 70;       // Communication error on send
+    enum EPROTO             = 71;       // Protocol error
+    enum EMULTIHOP          = 72;       // Multihop attempted
+    enum EDOTDOT            = 73;       // RFS specific error
+    enum EBADMSG            = 74;       // Not a data message
+    enum EOVERFLOW          = 75;       // Value too large for defined data type
+    enum ENOTUNIQ           = 76;       // Name not unique on network
+    enum EBADFD             = 77;       // File descriptor in bad state
+    enum EREMCHG            = 78;       // Remote address changed
+    enum ELIBACC            = 79;       // Can not access a needed shared library
+    enum ELIBBAD            = 80;       // Accessing a corrupted shared library
+    enum ELIBSCN            = 81;       // .lib section in a.out corrupted
+    enum ELIBMAX            = 82;       // Attempting to link in too many shared libraries
+    enum ELIBEXEC           = 83;       // Cannot exec a shared library directly
+    enum EILSEQ             = 84;       // Illegal byte sequence
+    enum ERESTART           = 85;       // Interrupted system call should be restarted
+    enum ESTRPIPE           = 86;       // Streams pipe error
+    enum EUSERS             = 87;       // Too many users
+    enum ENOTSOCK           = 88;       // Socket operation on non-socket
+    enum EDESTADDRREQ       = 89;       // Destination address required
+    enum EMSGSIZE           = 90;       // Message too long
+    enum EPROTOTYPE         = 91;       // Protocol wrong type for socket
+    enum ENOPROTOOPT        = 92;       // Protocol not available
+    enum EPROTONOSUPPORT    = 93;       // Protocol not supported
+    enum ESOCKTNOSUPPORT    = 94;       // Socket type not supported
+    enum EOPNOTSUPP         = 95;       // Operation not supported on transport endpoint
+    enum EPFNOSUPPORT       = 96;       // Protocol family not supported
+    enum EAFNOSUPPORT       = 97;       // Address family not supported by protocol
+    enum EADDRINUSE         = 98;       // Address already in use
+    enum EADDRNOTAVAIL      = 99;       // Cannot assign requested address
+    enum ENETDOWN           = 100;      // Network is down
+    enum ENETUNREACH        = 101;      // Network is unreachable
+    enum ENETRESET          = 102;      // Network dropped connection because of reset
+    enum ECONNABORTED       = 103;      // Software caused connection abort
+    enum ECONNRESET         = 104;      // Connection reset by peer
+    enum ENOBUFS            = 105;      // No buffer space available
+    enum EISCONN            = 106;      // Transport endpoint is already connected
+    enum ENOTCONN           = 107;      // Transport endpoint is not connected
+    enum ESHUTDOWN          = 108;      // Cannot send after transport endpoint shutdown
+    enum ETOOMANYREFS       = 109;      // Too many references: cannot splice
+    enum ETIMEDOUT          = 110;      // Connection timed out
+    enum ECONNREFUSED       = 111;      // Connection refused
+    enum EHOSTDOWN          = 112;      // Host is down
+    enum EHOSTUNREACH       = 113;      // No route to host
+    enum EALREADY           = 114;      // Operation already in progress
+    enum EINPROGRESS        = 115;      // Operation now in progress
+    enum ESTALE             = 116;      // Stale NFS file handle
+    enum EUCLEAN            = 117;      // Structure needs cleaning
+    enum ENOTNAM            = 118;      // Not a XENIX named type file
+    enum ENAVAIL            = 119;      // No XENIX semaphores available
+    enum EISNAM             = 120;      // Is a named type file
+    enum EREMOTEIO          = 121;      // Remote I/O error
+    enum EDQUOT             = 122;      // Quota exceeded
+    enum ENOMEDIUM          = 123;      // No medium found
+    enum EMEDIUMTYPE        = 124;      // Wrong medium type
+    enum ECANCELED          = 125;      // Operation Canceled
+    enum ENOKEY             = 126;      // Required key not available
+    enum EKEYEXPIRED        = 127;      // Key has expired
+    enum EKEYREVOKED        = 128;      // Key has been revoked
+    enum EKEYREJECTED       = 129;      // Key was rejected by service
+    enum EOWNERDEAD         = 130;      // Owner died
+    enum ENOTRECOVERABLE    = 131;      // State not recoverable
+}
+else version( OSX )
+{
+    enum EPERM              = 1;        // Operation not permitted
+    enum ENOENT             = 2;        // No such file or directory
+    enum ESRCH              = 3;        // No such process
+    enum EINTR              = 4;        // Interrupted system call
+    enum EIO                = 5;        // Input/output error
+    enum ENXIO              = 6;        // Device not configured
+    enum E2BIG              = 7;        // Argument list too long
+    enum ENOEXEC            = 8;        // Exec format error
+    enum EBADF              = 9;        // Bad file descriptor
+    enum ECHILD             = 10;       // No child processes
+    enum EDEADLK            = 11;       // Resource deadlock avoided
+    enum ENOMEM             = 12;       // Cannot allocate memory
+    enum EACCES             = 13;       // Permission denied
+    enum EFAULT             = 14;       // Bad address
+    enum EBUSY              = 16;       // Device busy
+    enum EEXIST             = 17;       // File exists
+    enum EXDEV              = 18;       // Cross-device link
+    enum ENODEV             = 19;       // Operation not supported by device
+    enum ENOTDIR            = 20;       // Not a directory
+    enum EISDIR             = 21;       // Is a directory
+    enum EINVAL             = 22;       // Invalid argument
+    enum ENFILE             = 23;       // Too many open files in system
+    enum EMFILE             = 24;       // Too many open files
+    enum ENOTTY             = 25;       // Inappropriate ioctl for device
+    enum ETXTBSY            = 26;       // Text file busy
+    enum EFBIG              = 27;       // File too large
+    enum ENOSPC             = 28;       // No space left on device
+    enum ESPIPE             = 29;       // Illegal seek
+    enum EROFS              = 30;       // Read-only file system
+    enum EMLINK             = 31;       // Too many links
+    enum EPIPE              = 32;       // Broken pipe
+    enum EDOM               = 33;       // Numerical argument out of domain
+    enum ERANGE             = 34;       // Result too large
+    enum EAGAIN             = 35;       // Resource temporarily unavailable
+    enum EWOULDBLOCK        = EAGAIN;   // Operation would block
+    enum EINPROGRESS        = 36;       // Operation now in progress
+    enum EALREADY           = 37;       // Operation already in progress
+    enum ENOTSOCK           = 38;       // Socket operation on non-socket
+    enum EDESTADDRREQ       = 39;       // Destination address required
+    enum EMSGSIZE           = 40;       // Message too long
+    enum EPROTOTYPE         = 41;       // Protocol wrong type for socket
+    enum ENOPROTOOPT        = 42;       // Protocol not available
+    enum EPROTONOSUPPORT    = 43;       // Protocol not supported
+    enum ENOTSUP            = 45;       // Operation not supported
+    enum EOPNOTSUPP         = ENOTSUP;  // Operation not supported on socket
+    enum EAFNOSUPPORT       = 47;       // Address family not supported by protocol family
+    enum EADDRINUSE         = 48;       // Address already in use
+    enum EADDRNOTAVAIL      = 49;       // Can't assign requested address
+    enum ENETDOWN           = 50;       // Network is down
+    enum ENETUNREACH        = 51;       // Network is unreachable
+    enum ENETRESET          = 52;       // Network dropped connection on reset
+    enum ECONNABORTED       = 53;       // Software caused connection abort
+    enum ECONNRESET         = 54;       // Connection reset by peer
+    enum ENOBUFS            = 55;       // No buffer space available
+    enum EISCONN            = 56;       // Socket is already connected
+    enum ENOTCONN           = 57;       // Socket is not connected
+    enum ETIMEDOUT          = 60;       // Operation timed out
+    enum ECONNREFUSED       = 61;       // Connection refused
+    enum ELOOP              = 62;       // Too many levels of symbolic links
+    enum ENAMETOOLONG       = 63;       // File name too long
+    enum EHOSTUNREACH       = 65;       // No route to host
+    enum ENOTEMPTY          = 66;       // Directory not empty
+    enum EDQUOT             = 69;       // Disc quota exceeded
+    enum ESTALE             = 70;       // Stale NFS file handle
+    enum ENOLCK             = 77;       // No locks available
+    enum ENOSYS             = 78;       // Function not implemented
+    enum EOVERFLOW          = 84;       // Value too large to be stored in data type
+    enum ECANCELED          = 89;       // Operation canceled
+    enum EIDRM              = 90;       // Identifier removed
+    enum ENOMSG             = 91;       // No message of desired type
+    enum EILSEQ             = 92;       // Illegal byte sequence
+    enum EBADMSG            = 94;       // Bad message
+    enum EMULTIHOP          = 95;       // Reserved
+    enum ENODATA            = 96;       // No message available on STREAM
+    enum ENOLINK            = 97;       // Reserved
+    enum ENOSR              = 98;       // No STREAM resources
+    enum ENOSTR             = 99;       // Not a STREAM
+    enum EPROTO             = 100;      // Protocol error
+    enum ETIME              = 101;      // STREAM ioctl timeout
+    enum ELAST              = 101;      // Must be equal largest errno
+}
+else version( freebsd )
+{
+    enum EPERM              = 1;        // Operation not permitted
+    enum ENOENT             = 2;        // No such file or directory
+    enum ESRCH              = 3;        // No such process
+    enum EINTR              = 4;        // Interrupted system call
+    enum EIO                = 5;        // Input/output error
+    enum ENXIO              = 6;        // Device not configured
+    enum E2BIG              = 7;        // Argument list too long
+    enum ENOEXEC            = 8;        // Exec format error
+    enum EBADF              = 9;        // Bad file descriptor
+    enum ECHILD             = 10;       // No child processes
+    enum EDEADLK            = 11;       // Resource deadlock avoided
+    enum ENOMEM             = 12;       // Cannot allocate memory
+    enum EACCES             = 13;       // Permission denied
+    enum EFAULT             = 14;       // Bad address
+    enum ENOTBLK            = 15;       // Block device required
+    enum EBUSY              = 16;       // Device busy
+    enum EEXIST             = 17;       // File exists
+    enum EXDEV              = 18;       // Cross-device link
+    enum ENODEV             = 19;       // Operation not supported by device
+    enum ENOTDIR            = 20;       // Not a directory
+    enum EISDIR             = 21;       // Is a directory
+    enum EINVAL             = 22;       // Invalid argument
+    enum ENFILE             = 23;       // Too many open files in system
+    enum EMFILE             = 24;       // Too many open files
+    enum ENOTTY             = 25;       // Inappropriate ioctl for device
+    enum ETXTBSY            = 26;       // Text file busy
+    enum EFBIG              = 27;       // File too large
+    enum ENOSPC             = 28;       // No space left on device
+    enum ESPIPE             = 29;       // Illegal seek
+    enum EROFS              = 30;       // Read-only file system
+    enum EMLINK             = 31;       // Too many links
+    enum EPIPE              = 32;       // Broken pipe
+    enum EDOM               = 33;       // Numerical argument out of domain
+    enum ERANGE             = 34;       // Result too large
+    enum EAGAIN             = 35;       // Resource temporarily unavailable
+    enum EWOULDBLOCK        = EAGAIN;   // Operation would block
+    enum EINPROGRESS        = 36;       // Operation now in progress
+    enum EALREADY           = 37;       // Operation already in progress
+    enum ENOTSOCK           = 38;       // Socket operation on non-socket
+    enum EDESTADDRREQ       = 39;       // Destination address required
+    enum EMSGSIZE           = 40;       // Message too long
+    enum EPROTOTYPE         = 41;       // Protocol wrong type for socket
+    enum ENOPROTOOPT        = 42;       // Protocol not available
+    enum EPROTONOSUPPORT    = 43;       // Protocol not supported
+    enum ENOTSUP            = 45;       // Operation not supported
+    enum EOPNOTSUPP         = ENOTSUP;  // Operation not supported on socket
+    enum EAFNOSUPPORT       = 47;       // Address family not supported by protocol family
+    enum EADDRINUSE         = 48;       // Address already in use
+    enum EADDRNOTAVAIL      = 49;       // Can't assign requested address
+    enum ENETDOWN           = 50;       // Network is down
+    enum ENETUNREACH        = 51;       // Network is unreachable
+    enum ENETRESET          = 52;       // Network dropped connection on reset
+    enum ECONNABORTED       = 53;       // Software caused connection abort
+    enum ECONNRESET         = 54;       // Connection reset by peer
+    enum ENOBUFS            = 55;       // No buffer space available
+    enum EISCONN            = 56;       // Socket is already connected
+    enum ENOTCONN           = 57;       // Socket is not connected
+    enum ESHUTDOWN          = 58;       // Can't send after socket shutdown
+    enum ETOOMANYREFS       = 59;       // Too many refrences; can't splice
+    enum ETIMEDOUT          = 60;       // Operation timed out
+    enum ECONNREFUSED       = 61;       // Connection refused
+    enum ELOOP              = 62;       // Too many levels of symbolic links
+    enum ENAMETOOLONG       = 63;       // File name too long
+    enum EHOSTUNREACH       = 65;       // No route to host
+    enum ENOTEMPTY          = 66;       // Directory not empty
+    enum EPROCLIM           = 67;       // Too many processes
+    enum EUSERS             = 68;       // Too many users
+    enum EDQUOT             = 69;       // Disc quota exceeded
+    enum ESTALE             = 70;       // Stale NFS file handle
+    enum EREMOTE            = 71;       // Too many levels of remote in path
+    enum EBADRPC            = 72;       // RPC struct is bad
+    enum ERPCMISMATCH       = 73;       // RPC version wrong
+    enum EPROGUNAVAIL       = 74;       // RPC prog. not avail
+    enum EPROGMISMATCH      = 75;       // Program version wrong
+    enum EPROCUNAVAIL       = 76;       // Bad procedure for program
+    enum ENOLCK             = 77;       // No locks available
+    enum ENOSYS             = 78;       // Function not implemented
+    enum EFTYPE             = 79;       // Inappropriate file type or format
+    enum EAUTH              = 80;       // Authentication error
+    enum ENEEDAUTH          = 81;       // Need authenticator
+    enum EIDRM              = 82;       // Itendifier removed
+    enum ENOMSG             = 83;       // No message of desired type
+    enum EOVERFLOW          = 84;       // Value too large to be stored in data type
+    enum ECANCELED          = 85;       // Operation canceled
+    enum EILSEQ             = 86;       // Illegal byte sequence
+    enum ENOATTR            = 87;       // Attribute not found
+    enum EDOOFUS            = 88;       // Programming error
+    enum EBADMSG            = 89;       // Bad message
+    enum EMULTIHOP          = 90;       // Multihop attempted
+    enum ENOLINK            = 91;       // Link has been severed
+    enum EPROTO             = 92;       // Protocol error
+    enum ELAST              = 92;       // Must be equal largest errno
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/fenv.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,142 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.fenv;
+
+extern (C):
+
+version( Windows )
+{
+    struct fenv_t
+    {
+        ushort    status;
+        ushort    control;
+        ushort    round;
+        ushort[2] reserved;
+    }
+
+    alias int fexcept_t;
+}
+else version( linux )
+{
+    struct fenv_t
+    {
+        ushort __control_word;
+        ushort __unused1;
+        ushort __status_word;
+        ushort __unused2;
+        ushort __tags;
+        ushort __unused3;
+        uint   __eip;
+        ushort __cs_selector;
+        ushort __opcode;
+        uint   __data_offset;
+        ushort __data_selector;
+        ushort __unused5;
+    }
+
+    alias int fexcept_t;
+}
+else version ( OSX )
+{
+    version ( BigEndian )
+    {
+        alias uint fenv_t;
+        alias uint fexcept_t;
+    }
+    version ( LittleEndian )
+    {
+        struct fenv_t
+        {
+            ushort  __control;
+            ushort  __status;
+            uint    __mxcsr;
+            byte[8] __reserved;
+        }
+
+        alias ushort fexcept_t;
+    }
+}
+else version ( freebsd )
+{
+    struct fenv_t
+    {
+        ushort __control;
+        ushort __mxcsr_hi;
+        ushort __status;
+        ushort __mxcsr_lo;
+        uint __tag;
+        byte[16] __other;
+    }
+
+    alias ushort fexcept_t;
+}
+else
+{
+    static assert( false );
+}
+
+enum
+{
+    FE_INVALID      = 1,
+    FE_DENORMAL     = 2, // non-standard
+    FE_DIVBYZERO    = 4,
+    FE_OVERFLOW     = 8,
+    FE_UNDERFLOW    = 0x10,
+    FE_INEXACT      = 0x20,
+    FE_ALL_EXCEPT   = 0x3F,
+    FE_TONEAREST    = 0,
+    FE_UPWARD       = 0x800,
+    FE_DOWNWARD     = 0x400,
+    FE_TOWARDZERO   = 0xC00,
+}
+
+version( Windows )
+{
+    private extern fenv_t _FE_DFL_ENV;
+    fenv_t* FE_DFL_ENV = &_FE_DFL_ENV;
+}
+else version( linux )
+{
+    fenv_t* FE_DFL_ENV = cast(fenv_t*)(-1);
+}
+else version( OSX )
+{
+    private extern fenv_t _FE_DFL_ENV;
+    fenv_t* FE_DFL_ENV = &_FE_DFL_ENV;
+}
+else version( freebsd )
+{
+    private extern fenv_t __fe_dfl_env;
+    fenv_t* FE_DFL_ENV = &__fe_dfl_env;
+}
+else
+{
+    static assert( false );
+}
+
+void feraiseexcept(int excepts);
+void feclearexcept(int excepts);
+
+int fetestexcept(int excepts);
+int feholdexcept(fenv_t* envp);
+
+void fegetexceptflag(fexcept_t* flagp, int excepts);
+void fesetexceptflag(in fexcept_t* flagp, int excepts);
+
+int fegetround();
+int fesetround(int round);
+
+void fegetenv(fenv_t* envp);
+void fesetenv(in fenv_t* envp);
+void feupdateenv(in fenv_t* envp);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/float_.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,57 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.float_;
+
+extern (C):
+
+enum FLT_ROUNDS			= 1;
+enum FLT_EVAL_METHOD	= 2;
+enum FLT_RADIX			= 2;
+
+enum DECIMAL_DIG		= real.dig;
+enum FLT_DIG			= float.dig;
+enum DBL_DIG			= double.dig;
+enum LDBL_DIG			= real.dig;
+
+enum FLT_MANT_DIG		= float.mant_dig;
+enum DBL_MANT_DIG		= double.mant_dig;
+enum LDBL_MANT_DIG		= real.mant_dig;
+
+enum FLT_MIN			= float.min;
+enum DBL_MIN			= double.min;
+enum LDBL_MIN			= real.min;
+
+enum FLT_MAX			= float.max;
+enum DBL_MAX			= double.max;
+enum LDBL_MAX			= real.max;
+
+enum FLT_EPSILON		= float.epsilon;
+enum DBL_EPSILON		= double.epsilon;
+enum LDBL_EPSILON		= real.epsilon;
+
+enum FLT_MIN_EXP		= float.min_exp;
+enum DBL_MIN_EXP		= double.min_exp;
+enum LDBL_MIN_EXP		= real.min_exp;
+
+enum FLT_MAX_EXP		= float.max_exp;
+enum DBL_MAX_EXP		= double.max_exp;
+enum LDBL_MAX_EXP		= real.max_exp;
+
+enum FLT_MIN_10_EXP		= float.min_10_exp;
+enum DBL_MIN_10_EXP		= double.min_10_exp;
+enum LDBL_MIN_10_EXP	= real.min_10_exp;
+
+enum FLT_MAX_10_EXP		= float.max_10_exp;
+enum DBL_MAX_10_EXP		= double.max_10_exp;
+enum LDBL_MAX_10_EXP	= real.max_10_exp;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/inttypes.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,256 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.inttypes;
+
+public import core.stdc.stddef; // for wchar_t
+public import core.stdc.stdint; // required by spec
+
+extern (C):
+
+struct imaxdiv_t
+{
+    intmax_t    quot,
+                rem;
+}
+
+private alias immutable(char)* _cstr;
+
+enum _cstr PRId8            = "hhd";
+enum _cstr PRId16           = "hd";
+enum _cstr PRId32           = "ld";
+enum _cstr PRId64           = "lld";
+
+enum _cstr PRIdLEAST8       = "hhd";
+enum _cstr PRIdLEAST16      = "hd";
+enum _cstr PRIdLEAST32      = "ld";
+enum _cstr PRIdLEAST64      = "lld";
+
+enum _cstr PRIdFAST8        = "hhd";
+enum _cstr PRIdFAST16       = "d";
+enum _cstr PRIdFAST32       = "ld";
+enum _cstr PRIdFAST64       = "lld";
+
+enum _cstr PRIi8            = "hhi";
+enum _cstr PRIi16           = "hi";
+enum _cstr PRIi32           = "li";
+enum _cstr PRIi64           = "lli";
+
+enum _cstr PRIiLEAST8       = "hhi";
+enum _cstr PRIiLEAST16      = "hi";
+enum _cstr PRIiLEAST32      = "li";
+enum _cstr PRIiLEAST64      = "lli";
+
+enum _cstr PRIiFAST8        = "hhi";
+enum _cstr PRIiFAST16       = "i";
+enum _cstr PRIiFAST32       = "li";
+enum _cstr PRIiFAST64       = "lli";
+
+enum _cstr PRIo8            = "hho";
+enum _cstr PRIo16           = "ho";
+enum _cstr PRIo32           = "lo";
+enum _cstr PRIo64           = "llo";
+
+enum _cstr PRIoLEAST8       = "hho";
+enum _cstr PRIoLEAST16      = "ho";
+enum _cstr PRIoLEAST32      = "lo";
+enum _cstr PRIoLEAST64      = "llo";
+
+enum _cstr PRIoFAST8        = "hho";
+enum _cstr PRIoFAST16       = "o";
+enum _cstr PRIoFAST32       = "lo";
+enum _cstr PRIoFAST64       = "llo";
+
+enum _cstr PRIu8            = "hhu";
+enum _cstr PRIu16           = "hu";
+enum _cstr PRIu32           = "lu";
+enum _cstr PRIu64           = "llu";
+
+enum _cstr PRIuLEAST8       = "hhu";
+enum _cstr PRIuLEAST16      = "hu";
+enum _cstr PRIuLEAST32      = "lu";
+enum _cstr PRIuLEAST64      = "llu";
+
+enum _cstr PRIuFAST8        = "hhu";
+enum _cstr PRIuFAST16       = "u";
+enum _cstr PRIuFAST32       = "lu";
+enum _cstr PRIuFAST64       = "llu";
+
+enum _cstr PRIx8            = "hhx";
+enum _cstr PRIx16           = "hx";
+enum _cstr PRIx32           = "lx";
+enum _cstr PRIx64           = "llx";
+
+enum _cstr PRIxLEAST8       = "hhx";
+enum _cstr PRIxLEAST16      = "hx";
+enum _cstr PRIxLEAST32      = "lx";
+enum _cstr PRIxLEAST64      = "llx";
+
+enum _cstr PRIxFAST8        = "hhx";
+enum _cstr PRIxFAST16       = "x";
+enum _cstr PRIxFAST32       = "lx";
+enum _cstr PRIxFAST64       = "llx";
+
+enum _cstr PRIX8            = "hhX";
+enum _cstr PRIX16           = "hX";
+enum _cstr PRIX32           = "lX";
+enum _cstr PRIX64           = "llX";
+
+enum _cstr PRIXLEAST8       = "hhX";
+enum _cstr PRIXLEAST16      = "hX";
+enum _cstr PRIXLEAST32      = "lX";
+enum _cstr PRIXLEAST64      = "llX";
+
+enum _cstr PRIXFAST8        = "hhX";
+enum _cstr PRIXFAST16       = "X";
+enum _cstr PRIXFAST32       = "lX";
+enum _cstr PRIXFAST64       = "llX";
+
+enum _cstr SCNd8            = "hhd";
+enum _cstr SCNd16           = "hd";
+enum _cstr SCNd32           = "ld";
+enum _cstr SCNd64           = "lld";
+
+enum _cstr SCNdLEAST8       = "hhd";
+enum _cstr SCNdLEAST16      = "hd";
+enum _cstr SCNdLEAST32      = "ld";
+enum _cstr SCNdLEAST64      = "lld";
+
+enum _cstr SCNdFAST8        = "hhd";
+enum _cstr SCNdFAST16       = "d";
+enum _cstr SCNdFAST32       = "ld";
+enum _cstr SCNdFAST64       = "lld";
+
+enum _cstr SCNi8            = "hhd";
+enum _cstr SCNi16           = "hi";
+enum _cstr SCNi32           = "li";
+enum _cstr SCNi64           = "lli";
+
+enum _cstr SCNiLEAST8       = "hhd";
+enum _cstr SCNiLEAST16      = "hi";
+enum _cstr SCNiLEAST32      = "li";
+enum _cstr SCNiLEAST64      = "lli";
+
+enum _cstr SCNiFAST8        = "hhd";
+enum _cstr SCNiFAST16       = "i";
+enum _cstr SCNiFAST32       = "li";
+enum _cstr SCNiFAST64       = "lli";
+
+enum _cstr SCNo8            = "hhd";
+enum _cstr SCNo16           = "ho";
+enum _cstr SCNo32           = "lo";
+enum _cstr SCNo64           = "llo";
+
+enum _cstr SCNoLEAST8       = "hhd";
+enum _cstr SCNoLEAST16      = "ho";
+enum _cstr SCNoLEAST32      = "lo";
+enum _cstr SCNoLEAST64      = "llo";
+
+enum _cstr SCNoFAST8        = "hhd";
+enum _cstr SCNoFAST16       = "o";
+enum _cstr SCNoFAST32       = "lo";
+enum _cstr SCNoFAST64       = "llo";
+
+enum _cstr SCNu8            = "hhd";
+enum _cstr SCNu16           = "hu";
+enum _cstr SCNu32           = "lu";
+enum _cstr SCNu64           = "llu";
+
+enum _cstr SCNuLEAST8       = "hhd";
+enum _cstr SCNuLEAST16      = "hu";
+enum _cstr SCNuLEAST32      = "lu";
+enum _cstr SCNuLEAST64      = "llu";
+
+enum _cstr SCNuFAST8        = "hhd";
+enum _cstr SCNuFAST16       = "u";
+enum _cstr SCNuFAST32       = "lu";
+enum _cstr SCNuFAST64       = "llu";
+
+enum _cstr SCNx8            = "hhd";
+enum _cstr SCNx16           = "hx";
+enum _cstr SCNx32           = "lx";
+enum _cstr SCNx64           = "llx";
+
+enum _cstr SCNxLEAST8       = "hhd";
+enum _cstr SCNxLEAST16      = "hx";
+enum _cstr SCNxLEAST32      = "lx";
+enum _cstr SCNxLEAST64      = "llx";
+
+enum _cstr SCNxFAST8        = "hhd";
+enum _cstr SCNxFAST16       = "x";
+enum _cstr SCNxFAST32       = "lx";
+enum _cstr SCNxFAST64       = "llx";
+
+version( X86_64 )
+{
+    enum _cstr PRIdMAX      = PRId64;
+    enum _cstr PRIiMAX      = PRIi64;
+    enum _cstr PRIoMAX      = PRIo64;
+    enum _cstr PRIuMAX      = PRIu64;
+    enum _cstr PRIxMAX      = PRIx64;
+    enum _cstr PRIXMAX      = PRIX64;
+
+    enum _cstr SCNdMAX      = SCNd64;
+    enum _cstr SCNiMAX      = SCNi64;
+    enum _cstr SCNoMAX      = SCNo64;
+    enum _cstr SCNuMAX      = SCNu64;
+    enum _cstr SCNxMAX      = SCNx64;
+
+    enum _cstr PRIdPTR      = PRId64;
+    enum _cstr PRIiPTR      = PRIi64;
+    enum _cstr PRIoPTR      = PRIo64;
+    enum _cstr PRIuPTR      = PRIu64;
+    enum _cstr PRIxPTR      = PRIx64;
+    enum _cstr PRIXPTR      = PRIX64;
+
+    enum _cstr SCNdPTR      = SCNd64;
+    enum _cstr SCNiPTR      = SCNi64;
+    enum _cstr SCNoPTR      = SCNo64;
+    enum _cstr SCNuPTR      = SCNu64;
+    enum _cstr SCNxPTR      = SCNx64;
+}
+else
+{
+    enum _cstr PRIdMAX      = PRId32;
+    enum _cstr PRIiMAX      = PRIi32;
+    enum _cstr PRIoMAX      = PRIo32;
+    enum _cstr PRIuMAX      = PRIu32;
+    enum _cstr PRIxMAX      = PRIx32;
+    enum _cstr PRIXMAX      = PRIX32;
+
+    enum _cstr SCNdMAX      = SCNd32;
+    enum _cstr SCNiMAX      = SCNi32;
+    enum _cstr SCNoMAX      = SCNo32;
+    enum _cstr SCNuMAX      = SCNu32;
+    enum _cstr SCNxMAX      = SCNx32;
+
+    enum _cstr PRIdPTR      = PRId32;
+    enum _cstr PRIiPTR      = PRIi32;
+    enum _cstr PRIoPTR      = PRIo32;
+    enum _cstr PRIuPTR      = PRIu32;
+    enum _cstr PRIxPTR      = PRIx32;
+    enum _cstr PRIXPTR      = PRIX32;
+
+    enum _cstr SCNdPTR      = SCNd32;
+    enum _cstr SCNiPTR      = SCNi32;
+    enum _cstr SCNoPTR      = SCNo32;
+    enum _cstr SCNuPTR      = SCNu32;
+    enum _cstr SCNxPTR      = SCNx32;
+}
+
+intmax_t  imaxabs(intmax_t j);
+imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom);
+intmax_t  strtoimax(in char* nptr, char** endptr, int base);
+uintmax_t strtoumax(in char* nptr, char** endptr, int base);
+intmax_t  wcstoimax(in wchar_t* nptr, wchar_t** endptr, int base);
+uintmax_t wcstoumax(in wchar_t* nptr, wchar_t** endptr, int base);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/limits.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,38 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.limits;
+
+private import core.stdc.config;
+
+extern (C):
+
+enum CHAR_BIT       = 8;
+enum SCHAR_MIN      = byte.min;
+enum SCHAR_MAX      = byte.max;
+enum UCHAR_MAX      = ubyte.min;
+enum CHAR_MIN       = char.max;
+enum CHAR_MAX       = char.max;
+enum MB_LEN_MAX     = 2;
+enum SHRT_MIN       = short.min;
+enum SHRT_MAX       = short.max;
+enum USHRT_MAX      = ushort.max;
+enum INT_MIN        = int.min;
+enum INT_MAX        = int.max;
+enum UINT_MAX       = uint.max;
+enum LONG_MIN       = c_long.min;
+enum LONG_MAX       = c_long.max;
+enum ULONG_MAX      = c_ulong.max;
+enum LLONG_MIN      = long.min;
+enum LLONG_MAX      = long.max;
+enum ULLONG_MAX     = ulong.max;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/locale.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,60 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.locale;
+
+extern (C):
+
+struct lconv
+{
+    char* decimal_point;
+    char* thousands_sep;
+    char* grouping;
+    char* int_curr_symbol;
+    char* currency_symbol;
+    char* mon_decimal_point;
+    char* mon_thousands_sep;
+    char* mon_grouping;
+    char* positive_sign;
+    char* negative_sign;
+    byte  int_frac_digits;
+    byte  frac_digits;
+    byte  p_cs_precedes;
+    byte  p_sep_by_space;
+    byte  n_cs_precedes;
+    byte  n_sep_by_space;
+    byte  p_sign_posn;
+    byte  n_sign_posn;
+    byte  int_p_cs_precedes;
+    byte  int_p_sep_by_space;
+    byte  int_n_cs_precedes;
+    byte  int_n_sep_by_space;
+    byte  int_p_sign_posn;
+    byte  int_n_sign_posn;
+}
+
+enum LC_CTYPE          = 0;
+enum LC_NUMERIC        = 1;
+enum LC_TIME           = 2;
+enum LC_COLLATE        = 3;
+enum LC_MONETARY       = 4;
+enum LC_ALL            = 6;
+enum LC_PAPER          = 7;  // non-standard
+enum LC_NAME           = 8;  // non-standard
+enum LC_ADDRESS        = 9;  // non-standard
+enum LC_TELEPHONE      = 10; // non-standard
+enum LC_MEASUREMENT    = 11; // non-standard
+enum LC_IDENTIFICATION = 12; // non-standard
+
+char*  setlocale(int category, in char* locale);
+lconv* localeconv();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/math.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,933 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.math;
+
+private import core.stdc.config;
+
+extern (C):
+
+alias float  float_t;
+alias double double_t;
+
+enum double HUGE_VAL      = double.infinity;
+enum double HUGE_VALF     = float.infinity;
+enum double HUGE_VALL     = real.infinity;
+
+enum float INFINITY       = float.infinity;
+enum float NAN            = float.nan;
+
+enum int FP_ILOGB0        = int.min;
+enum int FP_ILOGBNAN      = int.min;
+
+enum int MATH_ERRNO       = 1;
+enum int MATH_ERREXCEPT   = 2;
+enum int math_errhandling = MATH_ERRNO | MATH_ERREXCEPT;
+
+version( none )
+{
+    //
+    // these functions are all macros in C
+    //
+
+    //int fpclassify(real-floating x);
+    int fpclassify(float x);
+    int fpclassify(double x);
+    int fpclassify(real x);
+
+    //int isfinite(real-floating x);
+    int isfinite(float x);
+    int isfinite(double x);
+    int isfinite(real x);
+
+    //int isinf(real-floating x);
+    int isinf(float x);
+    int isinf(double x);
+    int isinf(real x);
+
+    //int isnan(real-floating x);
+    int isnan(float x);
+    int isnan(double x);
+    int isnan(real x);
+
+    //int isnormal(real-floating x);
+    int isnormal(float x);
+    int isnormal(double x);
+    int isnormal(real x);
+
+    //int signbit(real-floating x);
+    int signbit(float x);
+    int signbit(double x);
+    int signbit(real x);
+
+    //int isgreater(real-floating x, real-floating y);
+    int isgreater(float x, float y);
+    int isgreater(double x, double y);
+    int isgreater(real x, real y);
+
+    //int isgreaterequal(real-floating x, real-floating y);
+    int isgreaterequal(float x, float y);
+    int isgreaterequal(double x, double y);
+    int isgreaterequal(real x, real y);
+
+    //int isless(real-floating x, real-floating y);
+    int isless(float x, float y);
+    int isless(double x, double y);
+    int isless(real x, real y);
+
+    //int islessequal(real-floating x, real-floating y);
+    int islessequal(float x, float y);
+    int islessequal(double x, double y);
+    int islessequal(real x, real y);
+
+    //int islessgreater(real-floating x, real-floating y);
+    int islessgreater(float x, float y);
+    int islessgreater(double x, double y);
+    int islessgreater(real x, real y);
+
+    //int isunordered(real-floating x, real-floating y);
+    int isunordered(float x, float y);
+    int isunordered(double x, double y);
+    int isunordered(real x, real y);
+}
+
+version( DigitalMars ) version( Windows )
+    version = DigitalMarsWin32;
+
+version( DigitalMarsWin32 )
+{
+    enum
+    {
+        FP_NANS        = 0,
+        FP_NANQ        = 1,
+        FP_INFINITE    = 2,
+        FP_NORMAL      = 3,
+        FP_SUBNORMAL   = 4,
+        FP_ZERO        = 5,
+        FP_NAN         = FP_NANQ,
+        FP_EMPTY       = 6,
+        FP_UNSUPPORTED = 7,
+    }
+
+    enum
+    {
+        FP_FAST_FMA  = 0,
+        FP_FAST_FMAF = 0,
+        FP_FAST_FMAL = 0,
+    }
+
+    uint __fpclassify_f(float x);
+    uint __fpclassify_d(double x);
+    uint __fpclassify_ld(real x);
+
+  extern (D)
+  {
+    //int fpclassify(real-floating x);
+    int fpclassify(float x)     { return __fpclassify_f(x); }
+    int fpclassify(double x)    { return __fpclassify_d(x); }
+    int fpclassify(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? __fpclassify_d(x)
+            : __fpclassify_ld(x);
+    }
+
+    //int isfinite(real-floating x);
+    int isfinite(float x)       { return fpclassify(x) >= FP_NORMAL; }
+    int isfinite(double x)      { return fpclassify(x) >= FP_NORMAL; }
+    int isfinite(real x)        { return fpclassify(x) >= FP_NORMAL; }
+
+    //int isinf(real-floating x);
+    int isinf(float x)          { return fpclassify(x) == FP_INFINITE; }
+    int isinf(double x)         { return fpclassify(x) == FP_INFINITE; }
+    int isinf(real x)           { return fpclassify(x) == FP_INFINITE; }
+
+    //int isnan(real-floating x);
+    int isnan(float x)          { return fpclassify(x) <= FP_NANQ;   }
+    int isnan(double x)         { return fpclassify(x) <= FP_NANQ;   }
+    int isnan(real x)           { return fpclassify(x) <= FP_NANQ;   }
+
+    //int isnormal(real-floating x);
+    int isnormal(float x)       { return fpclassify(x) == FP_NORMAL; }
+    int isnormal(double x)      { return fpclassify(x) == FP_NORMAL; }
+    int isnormal(real x)        { return fpclassify(x) == FP_NORMAL; }
+
+    //int signbit(real-floating x);
+    int signbit(float x)     { return (cast(short*)&(x))[1] & 0x8000; }
+    int signbit(double x)    { return (cast(short*)&(x))[3] & 0x8000; }
+    int signbit(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? (cast(short*)&(x))[3] & 0x8000
+            : (cast(short*)&(x))[4] & 0x8000;
+    }
+  }
+}
+else version( linux )
+{
+    enum
+    {
+        FP_NAN,
+        FP_INFINITE,
+        FP_ZERO,
+        FP_SUBNORMAL,
+        FP_NORMAL,
+    }
+
+    enum
+    {
+        FP_FAST_FMA  = 0,
+        FP_FAST_FMAF = 0,
+        FP_FAST_FMAL = 0,
+    }
+
+    int __fpclassifyf(float x);
+    int __fpclassify(double x);
+    int __fpclassifyl(real x);
+
+    int __finitef(float x);
+    int __finite(double x);
+    int __finitel(real x);
+
+    int __isinff(float x);
+    int __isinf(double x);
+    int __isinfl(real x);
+
+    int __isnanf(float x);
+    int __isnan(double x);
+    int __isnanl(real x);
+
+    int __signbitf(float x);
+    int __signbit(double x);
+    int __signbitl(real x);
+
+  extern (D)
+  {
+    //int fpclassify(real-floating x);
+    int fpclassify(float x)     { return __fpclassifyf(x); }
+    int fpclassify(double x)    { return __fpclassify(x);  }
+    int fpclassify(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? __fpclassify(x)
+            : __fpclassifyl(x);
+    }
+
+    //int isfinite(real-floating x);
+    int isfinite(float x)       { return __finitef(x); }
+    int isfinite(double x)      { return __finite(x);  }
+    int isfinite(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? __finite(x)
+            : __finitel(x);
+    }
+
+    //int isinf(real-floating x);
+    int isinf(float x)          { return __isinff(x);  }
+    int isinf(double x)         { return __isinf(x);   }
+    int isinf(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? __isinf(x)
+            : __isinfl(x);
+    }
+
+    //int isnan(real-floating x);
+    int isnan(float x)          { return __isnanf(x);  }
+    int isnan(double x)         { return __isnan(x);   }
+    int isnan(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? __isnan(x)
+            : __isnanl(x);
+    }
+
+    //int isnormal(real-floating x);
+    int isnormal(float x)       { return fpclassify(x) == FP_NORMAL; }
+    int isnormal(double x)      { return fpclassify(x) == FP_NORMAL; }
+    int isnormal(real x)        { return fpclassify(x) == FP_NORMAL; }
+
+    //int signbit(real-floating x);
+    int signbit(float x)     { return __signbitf(x); }
+    int signbit(double x)    { return __signbit(x);  }
+    int signbit(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? __signbit(x)
+            : __signbitl(x);
+    }
+  }
+}
+else version( OSX )
+{
+    enum
+    {
+        FP_NAN         = 1,
+        FP_INFINITE    = 2,
+        FP_ZERO        = 3,
+        FP_NORMAL      = 4,
+        FP_SUBNORMAL   = 5,
+        FP_SUPERNORMAL = 6,
+    }
+
+    enum
+    {
+        FP_FAST_FMA  = 0,
+        FP_FAST_FMAF = 0,
+        FP_FAST_FMAL = 0,
+    }
+
+    int __fpclassifyf(float x);
+    int __fpclassifyd(double x);
+    int __fpclassify(real x);
+
+    int __isfinitef(float x);
+    int __isfinited(double x);
+    int __isfinite(real x);
+
+    int __isinff(float x);
+    int __isinfd(double x);
+    int __isinf(real x);
+
+    int __isnanf(float x);
+    int __isnand(double x);
+    int __isnan(real x);
+
+    int __signbitf(float x);
+    int __signbitd(double x);
+    int __signbitl(real x);
+
+  extern (D)
+  {
+    //int fpclassify(real-floating x);
+    int fpclassify(float x)     { return __fpclassifyf(x); }
+    int fpclassify(double x)    { return __fpclassifyd(x); }
+    int fpclassify(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? __fpclassifyd(x)
+            : __fpclassify(x);
+    }
+
+    //int isfinite(real-floating x);
+    int isfinite(float x)       { return __isfinitef(x); }
+    int isfinite(double x)      { return __isfinited(x); }
+    int isfinite(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? __isfinited(x)
+            : __isfinite(x);
+    }
+
+    //int isinf(real-floating x);
+    int isinf(float x)          { return __isinff(x); }
+    int isinf(double x)         { return __isinfd(x); }
+    int isinf(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? __isinfd(x)
+            : __isinf(x);
+    }
+
+    //int isnan(real-floating x);
+    int isnan(float x)          { return __isnanf(x); }
+    int isnan(double x)         { return __isnand(x); }
+    int isnan(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? __isnand(x)
+            : __isnan(x);
+    }
+
+    //int isnormal(real-floating x);
+    int isnormal(float x)       { return fpclassify(x) == FP_NORMAL; }
+    int isnormal(double x)      { return fpclassify(x) == FP_NORMAL; }
+    int isnormal(real x)        { return fpclassify(x) == FP_NORMAL; }
+
+    //int signbit(real-floating x);
+    int signbit(float x)     { return __signbitf(x); }
+    int signbit(double x)    { return __signbitd(x); }
+    int signbit(real x)
+    {
+        return (real.sizeof == double.sizeof)
+            ? __signbitd(x)
+            : __signbitl(x);
+    }
+  }
+}
+else version( freebsd )
+{
+    enum
+    {
+        FP_INFINITE  = 0x01,
+        FP_NAN       = 0x02,
+        FP_NORMAL    = 0x04,
+        FP_SUBNORMAL = 0x08,
+        FP_ZERO      = 0x10,
+    }
+
+    enum
+    {
+        FP_FAST_FMA  = 0,
+        FP_FAST_FMAF = 0,
+        FP_FAST_FMAL = 0,
+    }
+
+    int __fpclassifyd(double);
+    int __fpclassifyf(float);
+    int __fpclassifyl(real);
+    int __isfinitef(float);
+    int __isfinite(double);
+    int __isfinitel(real);
+    int __isinff(float);
+    int __isinfl(real);
+    int __isnanl(real);
+    int __isnormalf(float);
+    int __isnormal(double);
+    int __isnormall(real);
+    int __signbit(double);
+    int __signbitf(float);
+    int __signbitl(real);
+
+  extern (D)
+  {
+    //int fpclassify(real-floating x);
+    int fpclassify(float x)     { return __fpclassifyf(x); }
+    int fpclassify(double x)    { return __fpclassifyd(x); }
+    int fpclassify(real x)      { return __fpclassifyl(x); }
+
+    //int isfinite(real-floating x);
+    int isfinite(float x)       { return __isfinitef(x); }
+    int isfinite(double x)      { return __isfinite(x); }
+    int isfinite(real x)        { return __isfinitel(x); }
+
+    //int isinf(real-floating x);
+    int isinf(float x)          { return __isinff(x); }
+    int isinf(double x)         { return __isinfl(x); }
+    int isinf(real x)           { return __isinfl(x); }
+
+    //int isnan(real-floating x);
+    int isnan(float x)          { return __isnanl(x); }
+    int isnan(double x)         { return __isnanl(x); }
+    int isnan(real x)           { return __isnanl(x); }
+
+    //int isnormal(real-floating x);
+    int isnormal(float x)       { return __isnormalf(x); }
+    int isnormal(double x)      { return __isnormal(x); }
+    int isnormal(real x)        { return __isnormall(x); }
+
+    //int signbit(real-floating x);
+    int signbit(float x)        { return __signbitf(x); }
+    int signbit(double x)       { return __signbit(x); }
+    int signbit(real x)         { return __signbit(x); }
+  }
+}
+
+extern (D)
+{
+    //int isgreater(real-floating x, real-floating y);
+    int isgreater(float x, float y)        { return !(x !>  y); }
+    int isgreater(double x, double y)      { return !(x !>  y); }
+    int isgreater(real x, real y)          { return !(x !>  y); }
+
+    //int isgreaterequal(real-floating x, real-floating y);
+    int isgreaterequal(float x, float y)   { return !(x !>= y); }
+    int isgreaterequal(double x, double y) { return !(x !>= y); }
+    int isgreaterequal(real x, real y)     { return !(x !>= y); }
+
+    //int isless(real-floating x, real-floating y);
+    int isless(float x, float y)           { return !(x !<  y); }
+    int isless(double x, double y)         { return !(x !<  y); }
+    int isless(real x, real y)             { return !(x !<  y); }
+
+    //int islessequal(real-floating x, real-floating y);
+    int islessequal(float x, float y)      { return !(x !<= y); }
+    int islessequal(double x, double y)    { return !(x !<= y); }
+    int islessequal(real x, real y)        { return !(x !<= y); }
+
+    //int islessgreater(real-floating x, real-floating y);
+    int islessgreater(float x, float y)    { return !(x !<> y); }
+    int islessgreater(double x, double y)  { return !(x !<> y); }
+    int islessgreater(real x, real y)      { return !(x !<> y); }
+
+    //int isunordered(real-floating x, real-floating y);
+    int isunordered(float x, float y)      { return (x !<>= y); }
+    int isunordered(double x, double y)    { return (x !<>= y); }
+    int isunordered(real x, real y)        { return (x !<>= y); }
+}
+
+// NOTE: freebsd < 8-CURRENT doesn't appear to support *l, but we can
+//       approximate.
+version( freebsd )
+{
+    double  acos(double x);
+    float   acosf(float x);
+    real    acosl(real x) { return acos(x); }
+
+    double  asin(double x);
+    float   asinf(float x);
+    real    asinl(real x) { return asin(x); }
+
+    double  atan(double x);
+    float   atanf(float x);
+    real    atanl(real x) { return atan(x); }
+
+    double  atan2(double y, double x);
+    float   atan2f(float y, float x);
+    real    atan2l(real y, real x) { return atan2(y, x); }
+
+    double  cos(double x);
+    float   cosf(float x);
+    real    cosl(real x) { return cos(x); }
+
+    double  sin(double x);
+    float   sinf(float x);
+    real    sinl(real x) { return sin(x); }
+
+    double  tan(double x);
+    float   tanf(float x);
+    real    tanl(real x) { return tan(x); }
+
+    double  acosh(double x);
+    float   acoshf(float x);
+    real    acoshl(real x) { return acosh(x); }
+
+    double  asinh(double x);
+    float   asinhf(float x);
+    real    asinhl(real x) { return asinh(x); }
+
+    double  atanh(double x);
+    float   atanhf(float x);
+    real    atanhl(real x) { return atanh(x); }
+
+    double  cosh(double x);
+    float   coshf(float x);
+    real    coshl(real x) { return cosh(x); }
+
+    double  sinh(double x);
+    float   sinhf(float x);
+    real    sinhl(real x) { return sinh(x); }
+
+    double  tanh(double x);
+    float   tanhf(float x);
+    real    tanhl(real x) { return tanh(x); }
+
+    double  exp(double x);
+    float   expf(float x);
+    real    expl(real x) { return exp(x); }
+
+    double  exp2(double x);
+    float   exp2f(float x);
+    real    exp2l(real x) { return exp2(x); }
+
+    double  expm1(double x);
+    float   expm1f(float x);
+    real    expm1l(real x) { return expm1(x); }
+
+    double  frexp(double value, int* exp);
+    float   frexpf(float value, int* exp);
+    real    frexpl(real value, int* exp) { return frexp(value, exp); }
+
+    int     ilogb(double x);
+    int     ilogbf(float x);
+    int     ilogbl(real x) { return ilogb(x); }
+
+    double  ldexp(double x, int exp);
+    float   ldexpf(float x, int exp);
+    real    ldexpl(real x, int exp) { return ldexp(x, exp); }
+
+    double  log(double x);
+    float   logf(float x);
+    real    logl(real x) { return log(x); }
+
+    double  log10(double x);
+    float   log10f(float x);
+    real    log10l(real x) { return log10(x); }
+
+    double  log1p(double x);
+    float   log1pf(float x);
+    real    log1pl(real x) { return log1p(x); }
+
+    private enum real ONE_LN2 = 1 / 0x1.62e42fefa39ef358p-1L;
+    double  log2(double x) { return log(x) * ONE_LN2; }
+    float   log2f(float x) { return logf(x) * ONE_LN2; }
+    real    log2l(real x)  { return logl(x) * ONE_LN2; }
+
+    double  logb(double x);
+    float   logbf(float x);
+    real    logbl(real x) { return logb(x); }
+
+    double  modf(double value, double* iptr);
+    float   modff(float value, float* iptr);
+    //real    modfl(real value, real *iptr); // nontrivial conversion
+
+    double  scalbn(double x, int n);
+    float   scalbnf(float x, int n);
+    real    scalbnl(real x, int n) { return scalbn(x, n); }
+
+    double  scalbln(double x, c_long n);
+    float   scalblnf(float x, c_long n);
+    real    scalblnl(real x, c_long n) { return scalbln(x, n); }
+
+
+    double  cbrt(double x);
+    float   cbrtf(float x);
+    real    cbrtl(real x) { return cbrt(x); }
+
+    double  fabs(double x);
+    float   fabsf(float x);
+    real    fabsl(real x) { return fabs(x); }
+
+    double  hypot(double x, double y);
+    float   hypotf(float x, float y);
+    real    hypotl(real x, real y) { return hypot(x, y); }
+
+    double  pow(double x, double y);
+    float   powf(float x, float y);
+    real    powl(real x, real y) { return pow(x, y); }
+
+    double  sqrt(double x);
+    float   sqrtf(float x);
+    real    sqrtl(real x) { return sqrt(x); }
+
+    double  erf(double x);
+    float   erff(float x);
+    real    erfl(real x) { return erf(x); }
+
+    double  erfc(double x);
+    float   erfcf(float x);
+    real    erfcl(real x) { return erfc(x); }
+
+    double  lgamma(double x);
+    float   lgammaf(float x);
+    real    lgammal(real x) { return lgamma(x); }
+
+    double  tgamma(double x);
+    float   tgammaf(float x);
+    real    tgammal(real x) { return tgamma(x); }
+
+    double  ceil(double x);
+    float   ceilf(float x);
+    real    ceill(real x) { return ceil(x); }
+
+    double  floor(double x);
+    float   floorf(float x);
+    real    floorl(real x) { return floor(x); }
+
+    double  nearbyint(double x);
+    float   nearbyintf(float x);
+    real    nearbyintl(real x) { return nearbyint(x); }
+
+    double  rint(double x);
+    float   rintf(float x);
+    real    rintl(real x) { return rint(x); }
+
+    c_long  lrint(double x);
+    c_long  lrintf(float x);
+    c_long  lrintl(real x) { return lrint(x); }
+
+    long    llrint(double x);
+    long    llrintf(float x);
+    long    llrintl(real x) { return llrint(x); }
+
+    double  round(double x);
+    float   roundf(float x);
+    real    roundl(real x) { return round(x); }
+
+    c_long  lround(double x);
+    c_long  lroundf(float x);
+    c_long  lroundl(real x) { return lround(x); }
+
+    long    llround(double x);
+    long    llroundf(float x);
+    long    llroundl(real x) { return llround(x); }
+
+    double  trunc(double x);
+    float   truncf(float x);
+    real    truncl(real x) { return trunc(x); }
+
+    double  fmod(double x, double y);
+    float   fmodf(float x, float y);
+    real    fmodl(real x, real y) { return fmod(x, y); }
+
+    double  remainder(double x, double y);
+    float   remainderf(float x, float y);
+    real    remainderl(real x, real y) { return remainder(x, y); }
+
+    double  remquo(double x, double y, int* quo);
+    float   remquof(float x, float y, int* quo);
+    real    remquol(real x, real y, int* quo) { return remquo(x, y, quo); }
+
+    double  copysign(double x, double y);
+    float   copysignf(float x, float y);
+    real    copysignl(real x, real y) { return copysign(x, y); }
+
+//  double  nan(char* tagp);
+//  float   nanf(char* tagp);
+//  real    nanl(char* tagp);
+
+    double  nextafter(double x, double y);
+    float   nextafterf(float x, float y);
+    real    nextafterl(real x, real y) { return nextafter(x, y); }
+
+    double  nexttoward(double x, real y);
+    float   nexttowardf(float x, real y);
+    real    nexttowardl(real x, real y) { return nexttoward(x, y); }
+
+    double  fdim(double x, double y);
+    float   fdimf(float x, float y);
+    real    fdiml(real x, real y) { return fdim(x, y); }
+
+    double  fmax(double x, double y);
+    float   fmaxf(float x, float y);
+    real    fmaxl(real x, real y) { return fmax(x, y); }
+
+    double  fmin(double x, double y);
+    float   fminf(float x, float y);
+    real    fminl(real x, real y) { return fmin(x, y); }
+
+    double  fma(double x, double y, double z);
+    float   fmaf(float x, float y, float z);
+    real    fmal(real x, real y, real z) { return fma(x, y, z); }
+}
+else
+{
+    double  acos(double x);
+    float   acosf(float x);
+    real    acosl(real x);
+
+    double  asin(double x);
+    float   asinf(float x);
+    real    asinl(real x);
+
+    double  atan(double x);
+    float   atanf(float x);
+    real    atanl(real x);
+
+    double  atan2(double y, double x);
+    float   atan2f(float y, float x);
+    real    atan2l(real y, real x);
+
+    double  cos(double x);
+    float   cosf(float x);
+    real    cosl(real x);
+
+    double  sin(double x);
+    float   sinf(float x);
+    real    sinl(real x);
+
+    double  tan(double x);
+    float   tanf(float x);
+    real    tanl(real x);
+
+    double  acosh(double x);
+    float   acoshf(float x);
+    real    acoshl(real x);
+
+    double  asinh(double x);
+    float   asinhf(float x);
+    real    asinhl(real x);
+
+    double  atanh(double x);
+    float   atanhf(float x);
+    real    atanhl(real x);
+
+    double  cosh(double x);
+    float   coshf(float x);
+    real    coshl(real x);
+
+    double  sinh(double x);
+    float   sinhf(float x);
+    real    sinhl(real x);
+
+    double  tanh(double x);
+    float   tanhf(float x);
+    real    tanhl(real x);
+
+    double  exp(double x);
+    float   expf(float x);
+    real    expl(real x);
+
+    double  exp2(double x);
+    float   exp2f(float x);
+    real    exp2l(real x);
+
+    double  expm1(double x);
+    float   expm1f(float x);
+    real    expm1l(real x);
+
+    double  frexp(double value, int* exp);
+    float   frexpf(float value, int* exp);
+    real    frexpl(real value, int* exp);
+
+    int     ilogb(double x);
+    int     ilogbf(float x);
+    int     ilogbl(real x);
+
+    double  ldexp(double x, int exp);
+    float   ldexpf(float x, int exp);
+    real    ldexpl(real x, int exp);
+
+    double  log(double x);
+    float   logf(float x);
+    real    logl(real x);
+
+    double  log10(double x);
+    float   log10f(float x);
+    real    log10l(real x);
+
+    double  log1p(double x);
+    float   log1pf(float x);
+    real    log1pl(real x);
+
+    double  log2(double x);
+    float   log2f(float x);
+    real    log2l(real x);
+
+    double  logb(double x);
+    float   logbf(float x);
+    real    logbl(real x);
+
+    double  modf(double value, double* iptr);
+    float   modff(float value, float* iptr);
+    real    modfl(real value, real *iptr);
+
+    double  scalbn(double x, int n);
+    float   scalbnf(float x, int n);
+    real    scalbnl(real x, int n);
+
+    double  scalbln(double x, c_long n);
+    float   scalblnf(float x, c_long n);
+    real    scalblnl(real x, c_long n);
+
+    double  cbrt(double x);
+    float   cbrtf(float x);
+    real    cbrtl(real x);
+
+    double  fabs(double x);
+    float   fabsf(float x);
+    real    fabsl(real x);
+
+    double  hypot(double x, double y);
+    float   hypotf(float x, float y);
+    real    hypotl(real x, real y);
+
+    double  pow(double x, double y);
+    float   powf(float x, float y);
+    real    powl(real x, real y);
+
+    double  sqrt(double x);
+    float   sqrtf(float x);
+    real    sqrtl(real x);
+
+    double  erf(double x);
+    float   erff(float x);
+    real    erfl(real x);
+
+    double  erfc(double x);
+    float   erfcf(float x);
+    real    erfcl(real x);
+
+    double  lgamma(double x);
+    float   lgammaf(float x);
+    real    lgammal(real x);
+
+    double  tgamma(double x);
+    float   tgammaf(float x);
+    real    tgammal(real x);
+
+    double  ceil(double x);
+    float   ceilf(float x);
+    real    ceill(real x);
+
+    double  floor(double x);
+    float   floorf(float x);
+    real    floorl(real x);
+
+    double  nearbyint(double x);
+    float   nearbyintf(float x);
+    real    nearbyintl(real x);
+
+    double  rint(double x);
+    float   rintf(float x);
+    real    rintl(real x);
+
+    c_long  lrint(double x);
+    c_long  lrintf(float x);
+    c_long  lrintl(real x);
+
+    long    llrint(double x);
+    long    llrintf(float x);
+    long    llrintl(real x);
+
+    double  round(double x);
+    float   roundf(float x);
+    real    roundl(real x);
+
+    c_long  lround(double x);
+    c_long  lroundf(float x);
+    c_long  lroundl(real x);
+
+    long    llround(double x);
+    long    llroundf(float x);
+    long    llroundl(real x);
+
+    double  trunc(double x);
+    float   truncf(float x);
+    real    truncl(real x);
+
+    double  fmod(double x, double y);
+    float   fmodf(float x, float y);
+    real    fmodl(real x, real y);
+
+    double  remainder(double x, double y);
+    float   remainderf(float x, float y);
+    real    remainderl(real x, real y);
+
+    double  remquo(double x, double y, int* quo);
+    float   remquof(float x, float y, int* quo);
+    real    remquol(real x, real y, int* quo);
+
+    double  copysign(double x, double y);
+    float   copysignf(float x, float y);
+    real    copysignl(real x, real y);
+
+    double  nan(char* tagp);
+    float   nanf(char* tagp);
+    real    nanl(char* tagp);
+
+    double  nextafter(double x, double y);
+    float   nextafterf(float x, float y);
+    real    nextafterl(real x, real y);
+
+    double  nexttoward(double x, real y);
+    float   nexttowardf(float x, real y);
+    real    nexttowardl(real x, real y);
+
+    double  fdim(double x, double y);
+    float   fdimf(float x, float y);
+    real    fdiml(real x, real y);
+
+    double  fmax(double x, double y);
+    float   fmaxf(float x, float y);
+    real    fmaxl(real x, real y);
+
+    double  fmin(double x, double y);
+    float   fminf(float x, float y);
+    real    fminl(real x, real y);
+
+    double  fma(double x, double y, double z);
+    float   fmaf(float x, float y, float z);
+    real    fmal(real x, real y, real z);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/signal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,53 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.signal;
+
+extern (C):
+
+// this should be volatile
+alias int sig_atomic_t;
+
+private alias void function(int) sigfn_t;
+
+version( Posix )
+{
+    enum SIG_ERR    = cast(sigfn_t) -1;
+    enum SIG_DFL    = cast(sigfn_t) 0;
+    enum SIG_IGN    = cast(sigfn_t) 1;
+
+    // standard C signals
+    enum SIGABRT    = 6;  // Abnormal termination
+    enum SIGFPE     = 8;  // Floating-point error
+    enum SIGILL     = 4;  // Illegal hardware instruction
+    enum SIGINT     = 2;  // Terminal interrupt character
+    enum SIGSEGV    = 11; // Invalid memory reference
+    enum SIGTERM    = 15; // Termination
+}
+else
+{
+    enum SIG_ERR    = cast(sigfn_t) -1;
+    enum SIG_DFL    = cast(sigfn_t) 0;
+    enum SIG_IGN    = cast(sigfn_t) 1;
+
+    // standard C signals
+    enum SIGABRT    = 22; // Abnormal termination
+    enum SIGFPE     = 8;  // Floating-point error
+    enum SIGILL     = 4;  // Illegal hardware instruction
+    enum SIGINT     = 2;  // Terminal interrupt character
+    enum SIGSEGV    = 11; // Invalid memory reference
+    enum SIGTERM    = 15; // Termination
+}
+
+sigfn_t signal(int sig, sigfn_t func);
+int     raise(int sig);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/stdarg.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,45 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.stdarg;
+
+
+alias void* va_list;
+
+template va_start( T )
+{
+    void va_start( out va_list ap, inout T parmn )
+    {
+        ap = cast(va_list) ( cast(void*) &parmn + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) );
+    }
+}
+
+template va_arg( T )
+{
+    T va_arg( inout va_list ap )
+    {
+        T arg = *cast(T*) ap;
+        ap = cast(va_list) ( cast(void*) ap + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) );
+        return arg;
+    }
+}
+
+void va_end( va_list ap )
+{
+
+}
+
+void va_copy( out va_list dest, va_list src )
+{
+    dest = src;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/stddef.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,28 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.stddef;
+
+extern (C):
+
+//alias typeof(int.sizeof)                    size_t;
+//alias typeof(cast(void*)0 - cast(void*)0)   ptrdiff_t;
+
+version( Windows )
+{
+    alias wchar wchar_t;
+}
+else
+{
+    alias dchar wchar_t;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/stdint.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,154 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.stdint;
+
+private import core.stdc.stddef; // for ptrdiff_t, size_t, wchar_t
+private import core.stdc.signal; // for sig_atomic_t
+private import core.stdc.wchar_; // for wint_t
+
+private
+{
+    template typify(T)
+    {
+        T typify( T val ) { return val; }
+    }
+}
+
+extern (C):
+
+alias byte      int8_t;
+alias short     int16_t;
+alias int       int32_t;
+alias long      int64_t;
+//alias cent      int128_t;
+
+alias ubyte     uint8_t;
+alias ushort    uint16_t;
+alias uint      uint32_t;
+alias ulong     uint64_t;
+//alias ucent     uint128_t;
+
+alias byte      int_least8_t;
+alias short     int_least16_t;
+alias int       int_least32_t;
+alias long      int_least64_t;
+
+alias ubyte     uint_least8_t;
+alias ushort    uint_least16_t;
+alias uint      uint_least32_t;
+alias ulong     uint_least64_t;
+
+alias byte      int_fast8_t;
+alias int       int_fast16_t;
+alias int       int_fast32_t;
+alias long      int_fast64_t;
+
+alias ubyte     uint_fast8_t;
+alias uint      uint_fast16_t;
+alias uint      uint_fast32_t;
+alias ulong     uint_fast64_t;
+
+version( X86_64 )
+{
+    alias long  intptr_t;
+    alias ulong uintptr_t;
+}
+else
+{
+    alias int   intptr_t;
+    alias uint  uintptr_t;
+}
+
+alias long      intmax_t;
+alias ulong     uintmax_t;
+
+enum int8_t   INT8_MIN  = int8_t.min;
+enum int8_t   INT8_MAX  = int8_t.max;
+enum int16_t  INT16_MIN = int16_t.min;
+enum int16_t  INT16_MAX = int16_t.max;
+enum int32_t  INT32_MIN = int32_t.min;
+enum int32_t  INT32_MAX = int32_t.max;
+enum int64_t  INT64_MIN = int64_t.min;
+enum int64_t  INT64_MAX = int64_t.max;
+
+enum uint8_t  UINT8_MAX  = uint8_t.max;
+enum uint16_t UINT16_MAX = uint16_t.max;
+enum uint32_t UINT32_MAX = uint32_t.max;
+enum uint64_t UINT64_MAX = uint64_t.max;
+
+enum int_least8_t    INT_LEAST8_MIN   = int_least8_t.min;
+enum int_least8_t    INT_LEAST8_MAX   = int_least8_t.max;
+enum int_least16_t   INT_LEAST16_MIN  = int_least16_t.min;
+enum int_least16_t   INT_LEAST16_MAX  = int_least16_t.max;
+enum int_least32_t   INT_LEAST32_MIN  = int_least32_t.min;
+enum int_least32_t   INT_LEAST32_MAX  = int_least32_t.max;
+enum int_least64_t   INT_LEAST64_MIN  = int_least64_t.min;
+enum int_least64_t   INT_LEAST64_MAX  = int_least64_t.max;
+
+enum uint_least8_t   UINT_LEAST8_MAX  = uint_least8_t.max;
+enum uint_least16_t  UINT_LEAST16_MAX = uint_least16_t.max;
+enum uint_least32_t  UINT_LEAST32_MAX = uint_least32_t.max;
+enum uint_least64_t  UINT_LEAST64_MAX = uint_least64_t.max;
+
+enum int_fast8_t   INT_FAST8_MIN   = int_fast8_t.min;
+enum int_fast8_t   INT_FAST8_MAX   = int_fast8_t.max;
+enum int_fast16_t  INT_FAST16_MIN  = int_fast16_t.min;
+enum int_fast16_t  INT_FAST16_MAX  = int_fast16_t.max;
+enum int_fast32_t  INT_FAST32_MIN  = int_fast32_t.min;
+enum int_fast32_t  INT_FAST32_MAX  = int_fast32_t.max;
+enum int_fast64_t  INT_FAST64_MIN  = int_fast64_t.min;
+enum int_fast64_t  INT_FAST64_MAX  = int_fast64_t.max;
+
+enum uint_fast8_t  UINT_FAST8_MAX  = uint_fast8_t.max;
+enum uint_fast16_t UINT_FAST16_MAX = uint_fast16_t.max;
+enum uint_fast32_t UINT_FAST32_MAX = uint_fast32_t.max;
+enum uint_fast64_t UINT_FAST64_MAX = uint_fast64_t.max;
+
+enum intptr_t  INTPTR_MIN  = intptr_t.min;
+enum intptr_t  INTPTR_MAX  = intptr_t.max;
+
+enum uintptr_t UINTPTR_MIN = uintptr_t.min;
+enum uintptr_t UINTPTR_MAX = uintptr_t.max;
+
+enum intmax_t  INTMAX_MIN  = intmax_t.min;
+enum intmax_t  INTMAX_MAX  = intmax_t.max;
+
+enum uintmax_t UINTMAX_MAX = uintmax_t.max;
+
+enum ptrdiff_t PTRDIFF_MIN = ptrdiff_t.min;
+enum ptrdiff_t PTRDIFF_MAX = ptrdiff_t.max;
+
+enum sig_atomic_t SIG_ATOMIC_MIN = sig_atomic_t.min;
+enum sig_atomic_t SIG_ATOMIC_MAX = sig_atomic_t.max;
+
+enum size_t  SIZE_MAX  = size_t.max;
+
+enum wchar_t WCHAR_MIN = wchar_t.min;
+enum wchar_t WCHAR_MAX = wchar_t.max;
+
+enum wint_t  WINT_MIN  = wint_t.min;
+enum wint_t  WINT_MAX  = wint_t.max;
+
+alias typify!(int8_t)  INT8_C;
+alias typify!(int16_t) INT16_C;
+alias typify!(int32_t) INT32_C;
+alias typify!(int64_t) INT64_C;
+
+alias typify!(uint8_t)  UINT8_C;
+alias typify!(uint16_t) UINT16_C;
+alias typify!(uint32_t) UINT32_C;
+alias typify!(uint64_t) UINT64_C;
+
+alias typify!(intmax_t)  INTMAX_C;
+alias typify!(uintmax_t) UINTMAX_C;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/stdio.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,411 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.stdio;
+
+private
+{
+    import core.stdc.config;
+    import core.stdc.stddef; // for size_t
+    import core.stdc.stdarg; // for va_list
+}
+
+extern (C):
+
+version( Windows )
+{
+    enum
+    {
+        BUFSIZ       = 0x4000,
+        EOF          = -1,
+        FOPEN_MAX    = 20,
+        FILENAME_MAX = 256, // 255 plus NULL
+        TMP_MAX      = 32767,
+        SYS_OPEN     = 20,      // non-standard
+    }
+
+    enum int     _NFILE     = 60;       // non-standard
+    enum string  _P_tmpdir  = "\\"; // non-standard
+    enum wstring _wP_tmpdir = "\\"; // non-standard
+    enum int     L_tmpnam   = _P_tmpdir.length + 12;
+}
+else version( linux )
+{
+    enum
+    {
+        BUFSIZ       = 8192,
+        EOF          = -1,
+        FOPEN_MAX    = 16,
+        FILENAME_MAX = 4095,
+        TMP_MAX      = 238328,
+        L_tmpnam     = 20
+    }
+}
+else version( OSX )
+{
+    enum
+    {
+        BUFSIZ       = 1024,
+        EOF          = -1,
+        FOPEN_MAX    = 20,
+        FILENAME_MAX = 1024,
+        TMP_MAX      = 308915776,
+        L_tmpnam     = 1024,
+    }
+
+    private
+    {
+        struct __sbuf
+        {
+            ubyte*  _base;
+            int     _size;
+        }
+
+        struct __sFILEX
+        {
+
+        }
+    }
+}
+else version ( FreeBSD )
+{
+    enum
+    {
+        EOF          = -1,
+        FOPEN_MAX    = 20,
+        FILENAME_MAX = 1024,
+        TMP_MAX      = 308915776,
+        L_tmpnam     = 1024
+    }
+
+    private
+    {
+        struct __sbuf
+        {
+            ubyte *_base;
+            int _size;
+        }
+        struct __sFILEX
+        {
+
+        }
+    }
+}
+else
+{
+    static assert( false );
+}
+
+enum
+{
+    SEEK_SET,
+    SEEK_CUR,
+    SEEK_END
+}
+
+struct _iobuf
+{
+    align (1):
+    version( Windows )
+    {
+        char* _ptr;
+        int   _cnt;
+        char* _base;
+        int   _flag;
+        int   _file;
+        int   _charbuf;
+        int   _bufsiz;
+        int   __tmpnum;
+    }
+    else version( linux )
+    {
+        char*   _read_ptr;
+        char*   _read_end;
+        char*   _read_base;
+        char*   _write_base;
+        char*   _write_ptr;
+        char*   _write_end;
+        char*   _buf_base;
+        char*   _buf_end;
+        char*   _save_base;
+        char*   _backup_base;
+        char*   _save_end;
+        void*   _markers;
+        _iobuf* _chain;
+        int     _fileno;
+        int     _blksize;
+        int     _old_offset;
+        ushort  _cur_column;
+        byte    _vtable_offset;
+        char[1] _shortbuf;
+        void*   _lock;
+    }
+    else version( OSX )
+    {
+        ubyte*    _p;
+        int       _r;
+        int       _w;
+        short     _flags;
+        short     _file;
+        __sbuf    _bf;
+        int       _lbfsize;
+
+        int* function(void*)                    _close;
+        int* function(void*, char*, int)        _read;
+        fpos_t* function(void*, fpos_t, int)    _seek;
+        int* function(void*, char *, int)       _write;
+
+        __sbuf    _ub;
+        __sFILEX* _extra;
+        int       _ur;
+
+        ubyte[3]  _ubuf;
+        ubyte[1]  _nbuf;
+
+        __sbuf    _lb;
+
+        int       _blksize;
+        fpos_t    _offset;
+    }
+    else version( FreeBSD )
+    {
+        ubyte*    _p;
+        int       _r;
+        int       _w;
+        short     _flags;
+        short     _file;
+        __sbuf    _bf;
+        int       _lbfsize;
+
+        void* function()                        _cookie;
+        int* function(void*)                    _close;
+        int* function(void*, char*, int)        _read;
+        fpos_t* function(void*, fpos_t, int)    _seek;
+        int* function(void*, char *, int)       _write;
+
+        __sbuf    _ub;
+        __sFILEX* _extra;
+        int       _ur;
+
+        ubyte[3]  _ubuf;
+        ubyte[1]  _nbuf;
+
+        __sbuf    _lb;
+
+        int       _blksize;
+        fpos_t    _offset;
+    }
+    else
+    {
+        static assert( false );
+    }
+}
+
+alias shared(_iobuf) FILE;
+
+enum
+{
+    _F_RDWR = 0x0003, // non-standard
+    _F_READ = 0x0001, // non-standard
+    _F_WRIT = 0x0002, // non-standard
+    _F_BUF  = 0x0004, // non-standard
+    _F_LBUF = 0x0008, // non-standard
+    _F_ERR  = 0x0010, // non-standard
+    _F_EOF  = 0x0020, // non-standard
+    _F_BIN  = 0x0040, // non-standard
+    _F_IN   = 0x0080, // non-standard
+    _F_OUT  = 0x0100, // non-standard
+    _F_TERM = 0x0200, // non-standard
+}
+
+version( Windows )
+{
+    enum
+    {
+        _IOFBF   = 0,
+        _IOLBF   = 0x40,
+        _IONBF   = 4,
+        _IOREAD  = 1,     // non-standard
+        _IOWRT   = 2,     // non-standard
+        _IOMYBUF = 8,     // non-standard       
+        _IOEOF   = 0x10,  // non-standard
+        _IOERR   = 0x20,  // non-standard
+        _IOSTRG  = 0x40,  // non-standard
+        _IORW    = 0x80,  // non-standard
+        _IOTRAN  = 0x100, // non-standard
+        _IOAPP   = 0x200, // non-standard
+    }
+
+    extern shared void function() _fcloseallp;
+
+    private extern shared FILE[_NFILE] _iob;
+
+    shared stdin  = &_iob[0];
+    shared stdout = &_iob[1];
+    shared stderr = &_iob[2];
+    shared stdaux = &_iob[3];
+    shared stdprn = &_iob[4];
+}
+else version( linux )
+{
+    enum
+    {
+        _IOFBF = 0,
+        _IOLBF = 1,
+        _IONBF = 2,
+    }
+
+    extern shared FILE* stdin;
+    extern shared FILE* stdout;
+    extern shared FILE* stderr;
+}
+else version( OSX )
+{
+        enum
+    {
+        _IOFBF = 0,
+        _IOLBF = 1,
+        _IONBF = 2,
+    }
+
+    private extern shared FILE* __stdinp;
+    private extern shared FILE* __stdoutp;
+    private extern shared FILE* __stderrp;
+
+    alias __stdinp  stdin;
+    alias __stdoutp stdout;
+    alias __stderrp stderr;
+}
+else version( FreeBSD )
+{
+    private extern shared FILE[3] __sF;
+
+    shared stdin  = &__sF[0];
+    shared stdout = &__sF[1];
+    shared stderr = &__sF[2];
+}
+else
+{
+    static assert( false );
+}
+
+alias int fpos_t;
+
+int remove(in char* filename);
+int rename(in char* from, in char* to);
+
+FILE* tmpfile();
+char* tmpnam(char* s);
+
+int   fclose(FILE* stream);
+int   fflush(FILE* stream);
+FILE* fopen(in char* filename, in char* mode);
+FILE* freopen(in char* filename, in char* mode, FILE* stream);
+
+void setbuf(FILE* stream, char* buf);
+int  setvbuf(FILE* stream, char* buf, int mode, size_t size);
+
+int fprintf(FILE* stream, in char* format, ...);
+int fscanf(FILE* stream, in char* format, ...);
+int sprintf(char* s, in char* format, ...);
+int sscanf(in char* s, in char* format, ...);
+int vfprintf(FILE* stream, in char* format, va_list arg);
+int vfscanf(FILE* stream, in char* format, va_list arg);
+int vsprintf(char* s, in char* format, va_list arg);
+int vsscanf(in char* s, in char* format, va_list arg);
+int vprintf(in char* format, va_list arg);
+int vscanf(in char* format, va_list arg);
+int printf(in char* format, ...);
+int scanf(in char* format, ...);
+
+int fgetc(FILE* stream);
+int fputc(int c, FILE* stream);
+
+char* fgets(char* s, int n, FILE* stream);
+int   fputs(in char* s, FILE* stream);
+char* gets(char* s);
+int   puts(in char* s);
+
+extern (D)
+{
+    int getchar()                 { return getc(stdin);     }
+    int putchar(int c)            { return putc(c,stdout);  }
+    int getc(FILE* stream)        { return fgetc(stream);   }
+    int putc(int c, FILE* stream) { return fputc(c,stream); }
+}
+
+int ungetc(int c, FILE* stream);
+
+size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
+size_t fwrite(in void* ptr, size_t size, size_t nmemb, FILE* stream);
+
+int fgetpos(FILE* stream, fpos_t * pos);
+int fsetpos(FILE* stream, in fpos_t* pos);
+
+int    fseek(FILE* stream, c_long offset, int whence);
+c_long ftell(FILE* stream);
+
+version( Windows )
+{
+  extern (D)
+  {
+    void rewind(FILE* stream)   { fseek(stream,0L,SEEK_SET); stream._flag&=~_IOERR; }
+    void clearerr(FILE* stream) { stream._flag &= ~(_IOERR|_IOEOF);                 }
+    int  feof(FILE* stream)     { return stream._flag&_IOEOF;                       }
+    int  ferror(FILE* stream)   { return stream._flag&_IOERR;                       }
+  }
+    int   _snprintf(char* s, size_t n, in char* fmt, ...);
+    alias _snprintf snprintf;
+
+    int   _vsnprintf(char* s, size_t n, in char* format, va_list arg);
+    alias _vsnprintf vsnprintf;
+}
+else version( linux )
+{
+    void rewind(FILE* stream);
+    void clearerr(FILE* stream);
+    int  feof(FILE* stream);
+    int  ferror(FILE* stream);
+    int  fileno(FILE *);
+
+    int  snprintf(char* s, size_t n, in char* format, ...);
+    int  vsnprintf(char* s, size_t n, in char* format, va_list arg);
+}
+else version( OSX )
+{
+    void rewind(FILE*);
+    void clearerr(FILE*);
+    int  feof(FILE*);
+    int  ferror(FILE*);
+    int  fileno(FILE*);
+
+    int  snprintf(char* s, size_t n, in char* format, ...);
+    int  vsnprintf(char* s, size_t n, in char* format, va_list arg);
+}
+else version( FreeBSD )
+{
+    void rewind(FILE*);
+    void clearerr(FILE*);
+    int  feof(FILE*);
+    int  ferror(FILE*);
+    int  fileno(FILE*);
+
+    int  snprintf(char* s, size_t n, in char* format, ...);
+    int  vsnprintf(char* s, size_t n, in char* format, va_list arg);
+}
+else
+{
+    static assert( false );
+}
+
+void perror(in char* s);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/stdlib.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,93 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.stdlib;
+
+private import core.stdc.config;
+public import core.stdc.stddef; // for size_t, wchar_t
+
+extern (C):
+
+struct div_t
+{
+    int quot,
+        rem;
+}
+
+struct ldiv_t
+{
+    int quot,
+        rem;
+}
+
+struct lldiv_t
+{
+    long quot,
+         rem;
+}
+
+enum EXIT_SUCCESS = 0;
+enum EXIT_FAILURE = 1;
+enum RAND_MAX     = 32767;
+enum MB_CUR_MAX   = 1;
+
+double  atof(in char* nptr);
+int     atoi(in char* nptr);
+c_long  atol(in char* nptr);
+long    atoll(in char* nptr);
+
+double  strtod(in char* nptr, char** endptr);
+float   strtof(in char* nptr, char** endptr);
+real    strtold(in char* nptr, char** endptr);
+c_long  strtol(in char* nptr, char** endptr, int base);
+long    strtoll(in char* nptr, char** endptr, int base);
+c_ulong strtoul(in char* nptr, char** endptr, int base);
+ulong   strtoull(in char* nptr, char** endptr, int base);
+
+int     rand();
+void    srand(uint seed);
+
+void*   malloc(size_t size);
+void*   calloc(size_t nmemb, size_t size);
+void*   realloc(void* ptr, size_t size);
+void    free(void* ptr);
+
+void    abort();
+void    exit(int status);
+int     atexit(void function() func);
+void    _Exit(int status);
+
+char*   getenv(in char* name);
+int     system(in char* string);
+
+void*   bsearch(in void* key, in void* base, size_t nmemb, size_t size, int function(in void*, in void*) compar);
+void    qsort(void* base, size_t nmemb, size_t size, int function(in void*, in void*) compar);
+
+int     abs(int j);
+c_long  labs(c_long j);
+long    llabs(long j);
+
+div_t   div(int numer, int denom);
+ldiv_t  ldiv(c_long numer, c_long denom);
+lldiv_t lldiv(long numer, long denom);
+
+int     mblen(in char* s, size_t n);
+int     mbtowc(wchar_t* pwc, in char* s, size_t n);
+int     wctomb(char*s, wchar_t wc);
+size_t  mbstowcs(wchar_t* pwcs, in char* s, size_t n);
+size_t  wcstombs(char* s, in wchar_t* pwcs, size_t n);
+
+version( DigitalMars )
+{
+    void* alloca(size_t size); // non-standard
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/string.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,42 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.string;
+
+private import core.stdc.stddef; // for size_t
+
+extern (C):
+
+void* memchr(in void* s, int c, size_t n);
+int   memcmp(in void* s1, in void* s2, size_t n);
+void* memcpy(void* s1, in void* s2, size_t n);
+void* memmove(void* s1, in void* s2, size_t n);
+void* memset(void* s, int c, size_t n);
+
+char*  strcpy(char* s1, in char* s2);
+char*  strncpy(char* s1, in char* s2, size_t n);
+char*  strcat(char* s1, in char* s2);
+char*  strncat(char* s1, in char* s2, size_t n);
+int    strcmp(in char* s1, in char* s2);
+int    strcoll(in char* s1, in char* s2);
+int    strncmp(in char* s1, in char* s2, size_t n);
+size_t strxfrm(char* s1, in char* s2, size_t n);
+char*  strchr(in char* s, int c);
+size_t strcspn(in char* s1, in char* s2);
+char*  strpbrk(in char* s1, in char* s2);
+char*  strrchr(in char* s, int c);
+size_t strspn(in char* s1, in char* s2);
+char*  strstr(in char* s1, in char* s2);
+char*  strtok(char* s1, in char* s2);
+char*  strerror(int errnum);
+size_t strlen(in char* s);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/tgmath.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,657 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.tgmath;
+
+private import core.stdc.config;
+private static import core.stdc.math;
+private static import core.stdc.complex;
+
+extern (C):
+
+version( freebsd )
+{
+    alias core.stdc.math.acos          acos;
+    alias core.stdc.math.acosf         acos;
+    alias core.stdc.math.acosl         acos;
+
+    alias core.stdc.complex.cacos      acos;
+    alias core.stdc.complex.cacosf     acos;
+    alias core.stdc.complex.cacosl     acos;
+
+    alias core.stdc.math.asin          asin;
+    alias core.stdc.math.asinf         asin;
+    alias core.stdc.math.asinl         asin;
+
+    alias core.stdc.complex.casin      asin;
+    alias core.stdc.complex.casinf     asin;
+    alias core.stdc.complex.casinl     asin;
+
+    alias core.stdc.math.atan          atan;
+    alias core.stdc.math.atanf         atan;
+    alias core.stdc.math.atanl         atan;
+
+    alias core.stdc.complex.catan      atan;
+    alias core.stdc.complex.catanf     atan;
+    alias core.stdc.complex.catanl     atan;
+
+    alias core.stdc.math.atan2         atan2;
+    alias core.stdc.math.atan2f        atan2;
+    alias core.stdc.math.atan2l        atan2;
+
+    alias core.stdc.math.cos           cos;
+    alias core.stdc.math.cosf          cos;
+    alias core.stdc.math.cosl          cos;
+
+    alias core.stdc.complex.ccos       cos;
+    alias core.stdc.complex.ccosf      cos;
+    alias core.stdc.complex.ccosl      cos;
+
+    alias core.stdc.math.sin           sin;
+    alias core.stdc.math.sinf          sin;
+    alias core.stdc.math.sinl          sin;
+
+    alias core.stdc.complex.csin       csin;
+    alias core.stdc.complex.csinf      csin;
+    alias core.stdc.complex.csinl      csin;
+
+    alias core.stdc.math.tan           tan;
+    alias core.stdc.math.tanf          tan;
+    alias core.stdc.math.tanl          tan;
+
+    alias core.stdc.complex.ctan       tan;
+    alias core.stdc.complex.ctanf      tan;
+    alias core.stdc.complex.ctanl      tan;
+
+    alias core.stdc.math.acosh         acosh;
+    alias core.stdc.math.acoshf        acosh;
+    alias core.stdc.math.acoshl        acosh;
+
+    alias core.stdc.complex.cacosh     acosh;
+    alias core.stdc.complex.cacoshf    acosh;
+    alias core.stdc.complex.cacoshl    acosh;
+
+    alias core.stdc.math.asinh         asinh;
+    alias core.stdc.math.asinhf        asinh;
+    alias core.stdc.math.asinhl        asinh;
+
+    alias core.stdc.complex.casinh     asinh;
+    alias core.stdc.complex.casinhf    asinh;
+    alias core.stdc.complex.casinhl    asinh;
+
+    alias core.stdc.math.atanh         atanh;
+    alias core.stdc.math.atanhf        atanh;
+    alias core.stdc.math.atanhl        atanh;
+
+    alias core.stdc.complex.catanh     atanh;
+    alias core.stdc.complex.catanhf    atanh;
+    alias core.stdc.complex.catanhl    atanh;
+
+    alias core.stdc.math.cosh          cosh;
+    alias core.stdc.math.coshf         cosh;
+    alias core.stdc.math.coshl         cosh;
+
+    alias core.stdc.complex.ccosh      cosh;
+    alias core.stdc.complex.ccoshf     cosh;
+    alias core.stdc.complex.ccoshl     cosh;
+
+    alias core.stdc.math.sinh          sinh;
+    alias core.stdc.math.sinhf         sinh;
+    alias core.stdc.math.sinhl         sinh;
+
+    alias core.stdc.complex.csinh      sinh;
+    alias core.stdc.complex.csinhf     sinh;
+    alias core.stdc.complex.csinhl     sinh;
+
+    alias core.stdc.math.tanh          tanh;
+    alias core.stdc.math.tanhf         tanh;
+    alias core.stdc.math.tanhl         tanh;
+
+    alias core.stdc.complex.ctanh      tanh;
+    alias core.stdc.complex.ctanhf     tanh;
+    alias core.stdc.complex.ctanhl     tanh;
+
+    alias core.stdc.math.exp           exp;
+    alias core.stdc.math.expf          exp;
+    alias core.stdc.math.expl          exp;
+
+    alias core.stdc.complex.cexp       exp;
+    alias core.stdc.complex.cexpf      exp;
+    alias core.stdc.complex.cexpl      exp;
+
+    alias core.stdc.math.exp2          exp2;
+    alias core.stdc.math.exp2f         exp2;
+    alias core.stdc.math.exp2l         exp2;
+
+    alias core.stdc.math.expm1         expm1;
+    alias core.stdc.math.expm1f        expm1;
+    alias core.stdc.math.expm1l        expm1;
+
+    alias core.stdc.math.frexp         frexp;
+    alias core.stdc.math.frexpf        frexp;
+    alias core.stdc.math.frexpl        frexp;
+
+    alias core.stdc.math.ilogb         ilogb;
+    alias core.stdc.math.ilogbf        ilogb;
+    alias core.stdc.math.ilogbl        ilogb;
+
+    alias core.stdc.math.ldexp         ldexp;
+    alias core.stdc.math.ldexpf        ldexp;
+    alias core.stdc.math.ldexpl        ldexp;
+
+    alias core.stdc.math.log           log;
+    alias core.stdc.math.logf          log;
+    alias core.stdc.math.logl          log;
+
+    alias core.stdc.complex.clog       log;
+    alias core.stdc.complex.clogf      log;
+    alias core.stdc.complex.clogl      log;
+
+    alias core.stdc.math.log10         log10;
+    alias core.stdc.math.log10f        log10;
+    alias core.stdc.math.log10l        log10;
+
+    alias core.stdc.math.log1p         log1p;
+    alias core.stdc.math.log1pf        log1p;
+    alias core.stdc.math.log1pl        log1p;
+
+    alias core.stdc.math.log2          log1p;
+    alias core.stdc.math.log2f         log1p;
+    alias core.stdc.math.log2l         log1p;
+
+    alias core.stdc.math.logb          log1p;
+    alias core.stdc.math.logbf         log1p;
+    alias core.stdc.math.logbl         log1p;
+
+    alias core.stdc.math.modf          modf;
+    alias core.stdc.math.modff         modf;
+//  alias core.stdc.math.modfl         modf;
+
+    alias core.stdc.math.scalbn        scalbn;
+    alias core.stdc.math.scalbnf       scalbn;
+    alias core.stdc.math.scalbnl       scalbn;
+
+    alias core.stdc.math.scalbln       scalbln;
+    alias core.stdc.math.scalblnf      scalbln;
+    alias core.stdc.math.scalblnl      scalbln;
+
+    alias core.stdc.math.cbrt          cbrt;
+    alias core.stdc.math.cbrtf         cbrt;
+    alias core.stdc.math.cbrtl         cbrt;
+
+    alias core.stdc.math.fabs          fabs;
+    alias core.stdc.math.fabsf         fabs;
+    alias core.stdc.math.fabsl         fabs;
+
+    alias core.stdc.complex.cabs       fabs;
+    alias core.stdc.complex.cabsf      fabs;
+    alias core.stdc.complex.cabsl      fabs;
+
+    alias core.stdc.math.hypot         hypot;
+    alias core.stdc.math.hypotf        hypot;
+    alias core.stdc.math.hypotl        hypot;
+
+    alias core.stdc.math.pow           pow;
+    alias core.stdc.math.powf          pow;
+    alias core.stdc.math.powl          pow;
+
+    alias core.stdc.complex.cpow       pow;
+    alias core.stdc.complex.cpowf      pow;
+    alias core.stdc.complex.cpowl      pow;
+
+    alias core.stdc.math.sqrt          sqrt;
+    alias core.stdc.math.sqrtf         sqrt;
+    alias core.stdc.math.sqrtl         sqrt;
+
+    alias core.stdc.complex.csqrt      sqrt;
+    alias core.stdc.complex.csqrtf     sqrt;
+    alias core.stdc.complex.csqrtl     sqrt;
+
+    alias core.stdc.math.erf           erf;
+    alias core.stdc.math.erff          erf;
+    alias core.stdc.math.erfl          erf;
+
+    alias core.stdc.math.erfc          erfc;
+    alias core.stdc.math.erfcf         erfc;
+    alias core.stdc.math.erfcl         erfc;
+
+    alias core.stdc.math.lgamma        lgamma;
+    alias core.stdc.math.lgammaf       lgamma;
+    alias core.stdc.math.lgammal       lgamma;
+
+    alias core.stdc.math.tgamma        tgamma;
+    alias core.stdc.math.tgammaf       tgamma;
+    alias core.stdc.math.tgammal       tgamma;
+
+    alias core.stdc.math.ceil          ceil;
+    alias core.stdc.math.ceilf         ceil;
+    alias core.stdc.math.ceill         ceil;
+
+    alias core.stdc.math.floor         floor;
+    alias core.stdc.math.floorf        floor;
+    alias core.stdc.math.floorl        floor;
+
+    alias core.stdc.math.nearbyint     nearbyint;
+    alias core.stdc.math.nearbyintf    nearbyint;
+    alias core.stdc.math.nearbyintl    nearbyint;
+
+    alias core.stdc.math.rint          rint;
+    alias core.stdc.math.rintf         rint;
+    alias core.stdc.math.rintl         rint;
+
+    alias core.stdc.math.lrint         lrint;
+    alias core.stdc.math.lrintf        lrint;
+    alias core.stdc.math.lrintl        lrint;
+
+    alias core.stdc.math.llrint        llrint;
+    alias core.stdc.math.llrintf       llrint;
+    alias core.stdc.math.llrintl       llrint;
+
+    alias core.stdc.math.round         round;
+    alias core.stdc.math.roundf        round;
+    alias core.stdc.math.roundl        round;
+
+    alias core.stdc.math.lround        lround;
+    alias core.stdc.math.lroundf       lround;
+    alias core.stdc.math.lroundl       lround;
+
+    alias core.stdc.math.llround       llround;
+    alias core.stdc.math.llroundf      llround;
+    alias core.stdc.math.llroundl      llround;
+
+    alias core.stdc.math.trunc         trunc;
+    alias core.stdc.math.truncf        trunc;
+    alias core.stdc.math.truncl        trunc;
+
+    alias core.stdc.math.fmod          fmod;
+    alias core.stdc.math.fmodf         fmod;
+    alias core.stdc.math.fmodl         fmod;
+
+    alias core.stdc.math.remainder     remainder;
+    alias core.stdc.math.remainderf    remainder;
+    alias core.stdc.math.remainderl    remainder;
+
+    alias core.stdc.math.remquo        remquo;
+    alias core.stdc.math.remquof       remquo;
+    alias core.stdc.math.remquol       remquo;
+
+    alias core.stdc.math.copysign      copysign;
+    alias core.stdc.math.copysignf     copysign;
+    alias core.stdc.math.copysignl     copysign;
+
+//  alias core.stdc.math.nan           nan;
+//  alias core.stdc.math.nanf          nan;
+//  alias core.stdc.math.nanl          nan;
+
+    alias core.stdc.math.nextafter     nextafter;
+    alias core.stdc.math.nextafterf    nextafter;
+    alias core.stdc.math.nextafterl    nextafter;
+
+    alias core.stdc.math.nexttoward    nexttoward;
+    alias core.stdc.math.nexttowardf   nexttoward;
+    alias core.stdc.math.nexttowardl   nexttoward;
+
+    alias core.stdc.math.fdim          fdim;
+    alias core.stdc.math.fdimf         fdim;
+    alias core.stdc.math.fdiml         fdim;
+
+    alias core.stdc.math.fmax          fmax;
+    alias core.stdc.math.fmaxf         fmax;
+    alias core.stdc.math.fmaxl         fmax;
+
+    alias core.stdc.math.fmin          fmin;
+    alias core.stdc.math.fmin          fmin;
+    alias core.stdc.math.fminl         fmin;
+
+    alias core.stdc.math.fma           fma;
+    alias core.stdc.math.fmaf          fma;
+    alias core.stdc.math.fmal          fma;
+
+    alias core.stdc.complex.carg       carg;
+    alias core.stdc.complex.cargf      carg;
+    alias core.stdc.complex.cargl      carg;
+
+    alias core.stdc.complex.cimag      cimag;
+    alias core.stdc.complex.cimagf     cimag;
+    alias core.stdc.complex.cimagl     cimag;
+
+    alias core.stdc.complex.conj       conj;
+    alias core.stdc.complex.conjf      conj;
+    alias core.stdc.complex.conjl      conj;
+
+    alias core.stdc.complex.cproj      cproj;
+    alias core.stdc.complex.cprojf     cproj;
+    alias core.stdc.complex.cprojl     cproj;
+
+//  alias core.stdc.complex.creal      creal;
+//  alias core.stdc.complex.crealf     creal;
+//  alias core.stdc.complex.creall     creal;
+}
+else
+{
+    alias core.stdc.math.acos          acos;
+    alias core.stdc.math.acosf         acos;
+    alias core.stdc.math.acosl         acos;
+
+    alias core.stdc.complex.cacos      acos;
+    alias core.stdc.complex.cacosf     acos;
+    alias core.stdc.complex.cacosl     acos;
+
+    alias core.stdc.math.asin          asin;
+    alias core.stdc.math.asinf         asin;
+    alias core.stdc.math.asinl         asin;
+
+    alias core.stdc.complex.casin      asin;
+    alias core.stdc.complex.casinf     asin;
+    alias core.stdc.complex.casinl     asin;
+
+    alias core.stdc.math.atan          atan;
+    alias core.stdc.math.atanf         atan;
+    alias core.stdc.math.atanl         atan;
+
+    alias core.stdc.complex.catan      atan;
+    alias core.stdc.complex.catanf     atan;
+    alias core.stdc.complex.catanl     atan;
+
+    alias core.stdc.math.atan2         atan2;
+    alias core.stdc.math.atan2f        atan2;
+    alias core.stdc.math.atan2l        atan2;
+
+    alias core.stdc.math.cos           cos;
+    alias core.stdc.math.cosf          cos;
+    alias core.stdc.math.cosl          cos;
+
+    alias core.stdc.complex.ccos       cos;
+    alias core.stdc.complex.ccosf      cos;
+    alias core.stdc.complex.ccosl      cos;
+
+    alias core.stdc.math.sin           sin;
+    alias core.stdc.math.sinf          sin;
+    alias core.stdc.math.sinl          sin;
+
+    alias core.stdc.complex.csin       csin;
+    alias core.stdc.complex.csinf      csin;
+    alias core.stdc.complex.csinl      csin;
+
+    alias core.stdc.math.tan           tan;
+    alias core.stdc.math.tanf          tan;
+    alias core.stdc.math.tanl          tan;
+
+    alias core.stdc.complex.ctan       tan;
+    alias core.stdc.complex.ctanf      tan;
+    alias core.stdc.complex.ctanl      tan;
+
+    alias core.stdc.math.acosh         acosh;
+    alias core.stdc.math.acoshf        acosh;
+    alias core.stdc.math.acoshl        acosh;
+
+    alias core.stdc.complex.cacosh     acosh;
+    alias core.stdc.complex.cacoshf    acosh;
+    alias core.stdc.complex.cacoshl    acosh;
+
+    alias core.stdc.math.asinh         asinh;
+    alias core.stdc.math.asinhf        asinh;
+    alias core.stdc.math.asinhl        asinh;
+
+    alias core.stdc.complex.casinh     asinh;
+    alias core.stdc.complex.casinhf    asinh;
+    alias core.stdc.complex.casinhl    asinh;
+
+    alias core.stdc.math.atanh         atanh;
+    alias core.stdc.math.atanhf        atanh;
+    alias core.stdc.math.atanhl        atanh;
+
+    alias core.stdc.complex.catanh     atanh;
+    alias core.stdc.complex.catanhf    atanh;
+    alias core.stdc.complex.catanhl    atanh;
+
+    alias core.stdc.math.cosh          cosh;
+    alias core.stdc.math.coshf         cosh;
+    alias core.stdc.math.coshl         cosh;
+
+    alias core.stdc.complex.ccosh      cosh;
+    alias core.stdc.complex.ccoshf     cosh;
+    alias core.stdc.complex.ccoshl     cosh;
+
+    alias core.stdc.math.sinh          sinh;
+    alias core.stdc.math.sinhf         sinh;
+    alias core.stdc.math.sinhl         sinh;
+
+    alias core.stdc.complex.csinh      sinh;
+    alias core.stdc.complex.csinhf     sinh;
+    alias core.stdc.complex.csinhl     sinh;
+
+    alias core.stdc.math.tanh          tanh;
+    alias core.stdc.math.tanhf         tanh;
+    alias core.stdc.math.tanhl         tanh;
+
+    alias core.stdc.complex.ctanh      tanh;
+    alias core.stdc.complex.ctanhf     tanh;
+    alias core.stdc.complex.ctanhl     tanh;
+
+    alias core.stdc.math.exp           exp;
+    alias core.stdc.math.expf          exp;
+    alias core.stdc.math.expl          exp;
+
+    alias core.stdc.complex.cexp       exp;
+    alias core.stdc.complex.cexpf      exp;
+    alias core.stdc.complex.cexpl      exp;
+
+    alias core.stdc.math.exp2          exp2;
+    alias core.stdc.math.exp2f         exp2;
+    alias core.stdc.math.exp2l         exp2;
+
+    alias core.stdc.math.expm1         expm1;
+    alias core.stdc.math.expm1f        expm1;
+    alias core.stdc.math.expm1l        expm1;
+
+    alias core.stdc.math.frexp         frexp;
+    alias core.stdc.math.frexpf        frexp;
+    alias core.stdc.math.frexpl        frexp;
+
+    alias core.stdc.math.ilogb         ilogb;
+    alias core.stdc.math.ilogbf        ilogb;
+    alias core.stdc.math.ilogbl        ilogb;
+
+    alias core.stdc.math.ldexp         ldexp;
+    alias core.stdc.math.ldexpf        ldexp;
+    alias core.stdc.math.ldexpl        ldexp;
+
+    alias core.stdc.math.log           log;
+    alias core.stdc.math.logf          log;
+    alias core.stdc.math.logl          log;
+
+    alias core.stdc.complex.clog       log;
+    alias core.stdc.complex.clogf      log;
+    alias core.stdc.complex.clogl      log;
+
+    alias core.stdc.math.log10         log10;
+    alias core.stdc.math.log10f        log10;
+    alias core.stdc.math.log10l        log10;
+
+    alias core.stdc.math.log1p         log1p;
+    alias core.stdc.math.log1pf        log1p;
+    alias core.stdc.math.log1pl        log1p;
+
+    alias core.stdc.math.log2          log1p;
+    alias core.stdc.math.log2f         log1p;
+    alias core.stdc.math.log2l         log1p;
+
+    alias core.stdc.math.logb          log1p;
+    alias core.stdc.math.logbf         log1p;
+    alias core.stdc.math.logbl         log1p;
+
+    alias core.stdc.math.modf          modf;
+    alias core.stdc.math.modff         modf;
+    alias core.stdc.math.modfl         modf;
+
+    alias core.stdc.math.scalbn        scalbn;
+    alias core.stdc.math.scalbnf       scalbn;
+    alias core.stdc.math.scalbnl       scalbn;
+
+    alias core.stdc.math.scalbln       scalbln;
+    alias core.stdc.math.scalblnf      scalbln;
+    alias core.stdc.math.scalblnl      scalbln;
+
+    alias core.stdc.math.cbrt          cbrt;
+    alias core.stdc.math.cbrtf         cbrt;
+    alias core.stdc.math.cbrtl         cbrt;
+
+    alias core.stdc.math.fabs          fabs;
+    alias core.stdc.math.fabsf         fabs;
+    alias core.stdc.math.fabsl         fabs;
+
+    alias core.stdc.complex.cabs       fabs;
+    alias core.stdc.complex.cabsf      fabs;
+    alias core.stdc.complex.cabsl      fabs;
+
+    alias core.stdc.math.hypot         hypot;
+    alias core.stdc.math.hypotf        hypot;
+    alias core.stdc.math.hypotl        hypot;
+
+    alias core.stdc.math.pow           pow;
+    alias core.stdc.math.powf          pow;
+    alias core.stdc.math.powl          pow;
+
+    alias core.stdc.complex.cpow       pow;
+    alias core.stdc.complex.cpowf      pow;
+    alias core.stdc.complex.cpowl      pow;
+
+    alias core.stdc.math.sqrt          sqrt;
+    alias core.stdc.math.sqrtf         sqrt;
+    alias core.stdc.math.sqrtl         sqrt;
+
+    alias core.stdc.complex.csqrt      sqrt;
+    alias core.stdc.complex.csqrtf     sqrt;
+    alias core.stdc.complex.csqrtl     sqrt;
+
+    alias core.stdc.math.erf           erf;
+    alias core.stdc.math.erff          erf;
+    alias core.stdc.math.erfl          erf;
+
+    alias core.stdc.math.erfc          erfc;
+    alias core.stdc.math.erfcf         erfc;
+    alias core.stdc.math.erfcl         erfc;
+
+    alias core.stdc.math.lgamma        lgamma;
+    alias core.stdc.math.lgammaf       lgamma;
+    alias core.stdc.math.lgammal       lgamma;
+
+    alias core.stdc.math.tgamma        tgamma;
+    alias core.stdc.math.tgammaf       tgamma;
+    alias core.stdc.math.tgammal       tgamma;
+
+    alias core.stdc.math.ceil          ceil;
+    alias core.stdc.math.ceilf         ceil;
+    alias core.stdc.math.ceill         ceil;
+
+    alias core.stdc.math.floor         floor;
+    alias core.stdc.math.floorf        floor;
+    alias core.stdc.math.floorl        floor;
+
+    alias core.stdc.math.nearbyint     nearbyint;
+    alias core.stdc.math.nearbyintf    nearbyint;
+    alias core.stdc.math.nearbyintl    nearbyint;
+
+    alias core.stdc.math.rint          rint;
+    alias core.stdc.math.rintf         rint;
+    alias core.stdc.math.rintl         rint;
+
+    alias core.stdc.math.lrint         lrint;
+    alias core.stdc.math.lrintf        lrint;
+    alias core.stdc.math.lrintl        lrint;
+
+    alias core.stdc.math.llrint        llrint;
+    alias core.stdc.math.llrintf       llrint;
+    alias core.stdc.math.llrintl       llrint;
+
+    alias core.stdc.math.round         round;
+    alias core.stdc.math.roundf        round;
+    alias core.stdc.math.roundl        round;
+
+    alias core.stdc.math.lround        lround;
+    alias core.stdc.math.lroundf       lround;
+    alias core.stdc.math.lroundl       lround;
+
+    alias core.stdc.math.llround       llround;
+    alias core.stdc.math.llroundf      llround;
+    alias core.stdc.math.llroundl      llround;
+
+    alias core.stdc.math.trunc         trunc;
+    alias core.stdc.math.truncf        trunc;
+    alias core.stdc.math.truncl        trunc;
+
+    alias core.stdc.math.fmod          fmod;
+    alias core.stdc.math.fmodf         fmod;
+    alias core.stdc.math.fmodl         fmod;
+
+    alias core.stdc.math.remainder     remainder;
+    alias core.stdc.math.remainderf    remainder;
+    alias core.stdc.math.remainderl    remainder;
+
+    alias core.stdc.math.remquo        remquo;
+    alias core.stdc.math.remquof       remquo;
+    alias core.stdc.math.remquol       remquo;
+
+    alias core.stdc.math.copysign      copysign;
+    alias core.stdc.math.copysignf     copysign;
+    alias core.stdc.math.copysignl     copysign;
+
+    alias core.stdc.math.nan           nan;
+    alias core.stdc.math.nanf          nan;
+    alias core.stdc.math.nanl          nan;
+
+    alias core.stdc.math.nextafter     nextafter;
+    alias core.stdc.math.nextafterf    nextafter;
+    alias core.stdc.math.nextafterl    nextafter;
+
+    alias core.stdc.math.nexttoward    nexttoward;
+    alias core.stdc.math.nexttowardf   nexttoward;
+    alias core.stdc.math.nexttowardl   nexttoward;
+
+    alias core.stdc.math.fdim          fdim;
+    alias core.stdc.math.fdimf         fdim;
+    alias core.stdc.math.fdiml         fdim;
+
+    alias core.stdc.math.fmax          fmax;
+    alias core.stdc.math.fmaxf         fmax;
+    alias core.stdc.math.fmaxl         fmax;
+
+    alias core.stdc.math.fmin          fmin;
+    alias core.stdc.math.fmin          fmin;
+    alias core.stdc.math.fminl         fmin;
+
+    alias core.stdc.math.fma           fma;
+    alias core.stdc.math.fmaf          fma;
+    alias core.stdc.math.fmal          fma;
+
+    alias core.stdc.complex.carg       carg;
+    alias core.stdc.complex.cargf      carg;
+    alias core.stdc.complex.cargl      carg;
+
+    alias core.stdc.complex.cimag      cimag;
+    alias core.stdc.complex.cimagf     cimag;
+    alias core.stdc.complex.cimagl     cimag;
+
+    alias core.stdc.complex.conj       conj;
+    alias core.stdc.complex.conjf      conj;
+    alias core.stdc.complex.conjl      conj;
+
+    alias core.stdc.complex.cproj      cproj;
+    alias core.stdc.complex.cprojf     cproj;
+    alias core.stdc.complex.cprojl     cproj;
+
+//  alias core.stdc.complex.creal      creal;
+//  alias core.stdc.complex.crealf     creal;
+//  alias core.stdc.complex.creall     creal;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/time.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,98 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.time;
+
+private import core.stdc.config;
+private import core.stdc.stddef; // for size_t
+
+extern (C):
+
+version( Windows )
+{
+    struct tm
+    {
+        int     tm_sec;     // seconds after the minute - [0, 60]
+        int     tm_min;     // minutes after the hour - [0, 59]
+        int     tm_hour;    // hours since midnight - [0, 23]
+        int     tm_mday;    // day of the month - [1, 31]
+        int     tm_mon;     // months since January - [0, 11]
+        int     tm_year;    // years since 1900
+        int     tm_wday;    // days since Sunday - [0, 6]
+        int     tm_yday;    // days since January 1 - [0, 365]
+        int     tm_isdst;   // Daylight Saving Time flag
+    }
+}
+else
+{
+    struct tm
+    {
+        int     tm_sec;     // seconds after the minute [0-60]
+        int     tm_min;     // minutes after the hour [0-59]
+        int     tm_hour;    // hours since midnight [0-23]
+        int     tm_mday;    // day of the month [1-31]
+        int     tm_mon;     // months since January [0-11]
+        int     tm_year;    // years since 1900
+        int     tm_wday;    // days since Sunday [0-6]
+        int     tm_yday;    // days since January 1 [0-365]
+        int     tm_isdst;   // Daylight Savings Time flag
+        c_long  tm_gmtoff;  // offset from CUT in seconds
+        char*   tm_zone;    // timezone abbreviation
+    }
+}
+
+alias c_long time_t;
+alias c_long clock_t;
+
+version( Windows )
+{
+    clock_t CLOCKS_PER_SEC = 1000;
+}
+else version( OSX )
+{
+    clock_t CLOCKS_PER_SEC = 100;
+}
+else version( freebsd )
+{
+    clock_t CLOCKS_PER_SEC = 128;
+}
+else
+{
+    clock_t CLOCKS_PER_SEC = 1000000;
+}
+
+clock_t clock();
+double  difftime(time_t time1, time_t time0);
+time_t  mktime(tm* timeptr);
+time_t  time(time_t* timer);
+char*   asctime(in tm* timeptr);
+char*   ctime(in time_t* timer);
+tm*     gmtime(in time_t* timer);
+tm*     localtime(in time_t* timer);
+size_t  strftime(char* s, size_t maxsize, in char* format, in tm* timeptr);
+
+version( Windows )
+{
+    void  tzset();  		 // non-standard
+    void  _tzset(); 		 // non-standard
+    char* _strdate(char* s); // non-standard
+    char* _strtime(char* s); // non-standard
+}
+else version( linux )
+{
+    void tzset(); // non-standard
+}
+else version( freebsd )
+{
+    void tzset(); // non-standard
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/wchar_.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,108 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.wchar_;
+
+private import core.stdc.config;
+private import core.stdc.stdarg; // for va_list
+private import core.stdc.stdio;  // for FILE, not exposed per spec
+public import core.stdc.stddef;  // for size_t, wchar_t
+public import core.stdc.time;    // for tm
+public import core.stdc.stdint;  // for WCHAR_MIN, WCHAR_MAX
+
+extern (C):
+
+alias int     mbstate_t;
+alias wchar_t wint_t;
+
+enum wchar_t WEOF = 0xFFFF;
+
+int fwprintf(FILE* stream, in wchar_t* format, ...);
+int fwscanf(FILE* stream, in wchar_t* format, ...);
+int swprintf(wchar_t* s, size_t n, in wchar_t* format, ...);
+int swscanf(in wchar_t* s, in wchar_t* format, ...);
+int vfwprintf(FILE* stream, in wchar_t* format, va_list arg);
+int vfwscanf(FILE* stream, in wchar_t* format, va_list arg);
+int vswprintf(wchar_t* s, size_t n, in wchar_t* format, va_list arg);
+int vswscanf(in wchar_t* s, in wchar_t* format, va_list arg);
+int vwprintf(in wchar_t* format, va_list arg);
+int vwscanf(in wchar_t* format, va_list arg);
+int wprintf(in wchar_t* format, ...);
+int wscanf(in wchar_t* format, ...);
+
+wint_t fgetwc(FILE* stream);
+wint_t fputwc(wchar_t c, FILE* stream);
+
+wchar_t* fgetws(wchar_t* s, int n, FILE* stream);
+int      fputws(in wchar_t* s, FILE* stream);
+
+extern (D)
+{
+    wint_t getwchar()                     { return fgetwc(stdin);     }
+    wint_t putwchar(wchar_t c)            { return fputwc(c,stdout);  }
+    wint_t getwc(FILE* stream)            { return fgetwc(stream);    }
+    wint_t putwc(wchar_t c, FILE* stream) { return fputwc(c, stream); }
+}
+
+wint_t ungetwc(wint_t c, FILE* stream);
+int    fwide(FILE* stream, int mode);
+
+double  wcstod(in wchar_t* nptr, wchar_t** endptr);
+float   wcstof(in wchar_t* nptr, wchar_t** endptr);
+real    wcstold(in wchar_t* nptr, wchar_t** endptr);
+c_long  wcstol(in wchar_t* nptr, wchar_t** endptr, int base);
+long    wcstoll(in wchar_t* nptr, wchar_t** endptr, int base);
+c_ulong wcstoul(in wchar_t* nptr, wchar_t** endptr, int base);
+ulong   wcstoull(in wchar_t* nptr, wchar_t** endptr, int base);
+
+wchar_t* wcscpy(wchar_t* s1, in wchar_t* s2);
+wchar_t* wcsncpy(wchar_t* s1, in wchar_t* s2, size_t n);
+wchar_t* wcscat(wchar_t* s1, in wchar_t* s2);
+wchar_t* wcsncat(wchar_t* s1, in wchar_t* s2, size_t n);
+int      wcscmp(in wchar_t* s1, in wchar_t* s2);
+int      wcscoll(in wchar_t* s1, in wchar_t* s2);
+int      wcsncmp(in wchar_t* s1, in wchar_t* s2, size_t n);
+size_t   wcsxfrm(wchar_t* s1, in wchar_t* s2, size_t n);
+wchar_t* wcschr(in wchar_t* s, wchar_t c);
+size_t   wcscspn(in wchar_t* s1, in wchar_t* s2);
+wchar_t* wcspbrk(in wchar_t* s1, in wchar_t* s2);
+wchar_t* wcsrchr(in wchar_t* s, wchar_t c);
+size_t   wcsspn(in wchar_t* s1, in wchar_t* s2);
+wchar_t* wcsstr(in wchar_t* s1, in wchar_t* s2);
+wchar_t* wcstok(wchar_t* s1, in wchar_t* s2, wchar_t** ptr);
+size_t   wcslen(wchar_t* s);
+
+wchar_t* wmemchr(in wchar_t* s, wchar_t c, size_t n);
+int      wmemcmp(in wchar_t* s1, in wchar_t* s2, size_t n);
+wchar_t* wmemcpy(wchar_t* s1, in wchar_t* s2, size_t n);
+wchar_t* wmemmove(wchar_t*s1, in wchar_t* s2, size_t n);
+wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n);
+
+size_t wcsftime(wchar_t* s, size_t maxsize, in wchar_t* format, in tm* timeptr);
+
+version( Windows )
+{
+    wchar_t* _wasctime(tm*);      // non-standard
+    wchar_t* _wctime(time_t*);	  // non-standard
+    wchar_t* _wstrdate(wchar_t*); // non-standard
+    wchar_t* _wstrtime(wchar_t*); // non-standard
+}
+
+wint_t btowc(int c);
+int    wctob(wint_t c);
+int    mbsinit(in mbstate_t* ps);
+size_t mbrlen(in char* s, size_t n, mbstate_t* ps);
+size_t mbrtowc(wchar_t* pwc, in char* s, size_t n, mbstate_t* ps);
+size_t wcrtomb(char* s, wchar_t wc, mbstate_t* ps);
+size_t mbsrtowcs(wchar_t* dst, in char** src, size_t len, mbstate_t* ps);
+size_t wcsrtombs(char* dst, in wchar_t** src, size_t len, mbstate_t* ps);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/stdc/wctype.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,41 @@
+/**
+ * D header file for C99.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: ISO/IEC 9899:1999 (E)
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.stdc.wctype;
+
+public  import core.stdc.wchar_; // for wint_t, WEOF 
+
+extern (C):
+
+alias wchar_t wctrans_t;
+alias wchar_t wctype_t;
+
+int iswalnum(wint_t wc);
+int iswalpha(wint_t wc);
+int iswblank(wint_t wc);
+int iswcntrl(wint_t wc);
+int iswdigit(wint_t wc);
+int iswgraph(wint_t wc);
+int iswlower(wint_t wc);
+int iswprint(wint_t wc);
+int iswpunct(wint_t wc);
+int iswspace(wint_t wc);
+int iswupper(wint_t wc);
+int iswxdigit(wint_t wc);
+
+int       iswctype(wint_t wc, wctype_t desc);
+wctype_t  wctype(in char* property);
+wint_t    towlower(wint_t wc);
+wint_t    towupper(wint_t wc);
+wint_t    towctrans(wint_t wc, wctrans_t desc);
+wctrans_t wctrans(in char* property);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/osx/mach/kern_return.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,71 @@
+/**
+ * D header file for OSX.
+ *
+ * Copyright: Copyright Sean Kelly 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.osx.mach.kern_return;
+
+extern (C):
+
+alias int kern_return_t;
+
+enum : kern_return_t
+{
+    KERN_SUCCESS                = 0,
+    KERN_INVALID_ADDRESS        = 1,
+    KERN_PROTECTION_FAILURE     = 2,
+    KERN_NO_SPACE               = 3,
+    KERN_INVALID_ARGUMENT       = 4,
+    KERN_FAILURE                = 5,
+    KERN_RESOURCE_SHORTAGE      = 6,
+    KERN_NOT_RECEIVER           = 7,
+    KERN_NO_ACCESS              = 8,
+    KERN_MEMORY_FAILURE         = 9,
+    KERN_MEMORY_ERROR           = 10,
+    KERN_ALREADY_IN_SET         = 11,
+    KERN_NOT_IN_SET             = 12,
+    KERN_NAME_EXISTS            = 13,
+    KERN_ABORTED                = 14,
+    KERN_INVALID_NAME           = 15,
+    KERN_INVALID_TASK           = 16,
+    KERN_INVALID_RIGHT          = 17,
+    KERN_INVALID_VALUE          = 18,
+    KERN_UREFS_OVERFLOW         = 19,
+    KERN_INVALID_CAPABILITY     = 20,
+    KERN_RIGHT_EXISTS           = 21,
+    KERN_INVALID_HOST           = 22,
+    KERN_MEMORY_PRESENT         = 23,
+    KERN_MEMORY_DATA_MOVED      = 24,
+    KERN_MEMORY_RESTART_COPY    = 25,
+    KERN_INVALID_PROCESSOR_SET  = 26,
+    KERN_POLICY_LIMIT           = 27,
+    KERN_INVALID_POLICY         = 28,
+    KERN_INVALID_OBJECT         = 29,
+    KERN_ALREADY_WAITING        = 30,
+    KERN_DEFAULT_SET            = 31,
+    KERN_EXCEPTION_PROTECTED    = 32,
+    KERN_INVALID_LEDGER         = 33,
+    KERN_INVALID_MEMORY_CONTROL = 34,
+    KERN_INVALID_SECURITY       = 35,
+    KERN_NOT_DEPRESSED          = 36,
+    KERN_TERMINATED             = 37,
+    KERN_LOCK_SET_DESTROYED     = 38,
+    KERN_LOCK_UNSTABLE          = 39,
+    KERN_LOCK_OWNED             = 40,
+    KERN_LOCK_OWNED_SELF        = 41,
+    KERN_SEMAPHORE_DESTROYED    = 42,
+    KERN_RPC_SERVER_TERMINATED  = 43,
+    KERN_RPC_TERMINATE_ORPHAN   = 44,
+    KERN_RPC_CONTINUE_ORPHAN    = 45,
+    KERN_NOT_SUPPORTED          = 46,
+    KERN_NODE_DOWN              = 47,
+    KERN_OPERATION_TIMED_OUT    = 49,
+    KERN_RETURN_MAX             = 0x100,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/osx/mach/port.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,25 @@
+/**
+ * D header file for OSX.
+ *
+ * Copyright: Copyright Sean Kelly 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.osx.mach.port;
+
+extern (C):
+
+version( X86 )
+    version = i386;
+version( X86_64 )
+    version = i386;
+version( i386 )
+{
+    alias uint        natural_t;
+    alias natural_t   mach_port_t;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/osx/mach/semaphore.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,54 @@
+/**
+ * D header file for OSX.
+ *
+ * Copyright: Copyright Sean Kelly 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.osx.mach.semaphore;
+
+public import core.sys.osx.mach.kern_return;
+public import core.sys.osx.mach.port;
+
+extern (C):
+
+alias mach_port_t   task_t;
+alias mach_port_t   thread_t;
+alias mach_port_t   semaphore_t;
+alias int           sync_policy_t;
+
+alias int clock_res_t;
+struct mach_timespec_t
+{
+	uint	    tv_sec;
+	clock_res_t	tv_nsec;
+}
+
+enum
+{
+    SYNC_POLICY_FIFO            = 0x0,
+    SYNC_POLICY_FIXED_PRIORITY  = 0x1,
+    SYNC_POLICY_REVERSED        = 0x2,
+    SYNC_POLICY_ORDER_MASK      = 0x3,
+    SYNC_POLICY_LIFO            = (SYNC_POLICY_FIFO | SYNC_POLICY_REVERSED),
+    SYNC_POLICY_MAX			    = 0x7,
+}
+
+task_t        mach_task_self();
+kern_return_t semaphore_create(task_t, semaphore_t*, int, int);
+kern_return_t semaphore_destroy(task_t, semaphore_t);
+    
+kern_return_t semaphore_signal(semaphore_t);
+kern_return_t semaphore_signal_all(semaphore_t);
+kern_return_t semaphore_signal_thread(semaphore_t, thread_t);
+
+kern_return_t semaphore_wait(semaphore_t);
+kern_return_t semaphore_wait_signal(semaphore_t, semaphore_t);
+
+kern_return_t semaphore_timedwait(semaphore_t, mach_timespec_t);
+kern_return_t semaphore_timedwait_signal(semaphore_t, semaphore_t, mach_timespec_t);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/osx/mach/thread_act.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,124 @@
+/**
+ * D header file for OSX.
+ *
+ * Copyright: Copyright Sean Kelly 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.osx.mach.thread_act;
+
+public import core.sys.osx.mach.kern_return;
+public import core.sys.osx.mach.port;
+
+extern (C):
+
+version( X86 )
+    version = i386;
+version( X86_64 )
+    version = i386;
+version( i386 )
+{
+    alias mach_port_t thread_act_t;
+    alias void        thread_state_t;
+    alias int         thread_state_flavor_t;
+    alias natural_t   mach_msg_type_number_t;
+
+    enum
+    {
+        x86_THREAD_STATE32      = 1,
+        x86_FLOAT_STATE32       = 2,
+        x86_EXCEPTION_STATE32   = 3,
+        x86_THREAD_STATE64      = 4,
+        x86_FLOAT_STATE64       = 5,
+        x86_EXCEPTION_STATE64   = 6,
+        x86_THREAD_STATE        = 7,
+        x86_FLOAT_STATE         = 8,
+        x86_EXCEPTION_STATE     = 9,
+        x86_DEBUG_STATE32       = 10,
+        x86_DEBUG_STATE64       = 11,
+        x86_DEBUG_STATE         = 12,
+        THREAD_STATE_NONE       = 13,
+    }
+
+    struct x86_thread_state32_t
+    {
+        uint    eax;
+        uint    ebx;
+        uint    ecx;
+        uint    edx;
+        uint    edi;
+        uint    esi;
+        uint    ebp;
+        uint    esp;
+        uint    ss;
+        uint    eflags;
+        uint    eip;
+        uint    cs;
+        uint    ds;
+        uint    es;
+        uint    fs;
+        uint    gs;
+    }
+
+    struct x86_thread_state64_t
+    {
+        ulong   rax;
+        ulong   rbx;
+        ulong   rcx;
+        ulong   rdx;
+        ulong   rdi;
+        ulong   rsi;
+        ulong   rbp;
+        ulong   rsp;
+        ulong   r8;
+        ulong   r9;
+        ulong   r10;
+        ulong   r11;
+        ulong   r12;
+        ulong   r13;
+        ulong   r14;
+        ulong   r15;
+        ulong   rip;
+        ulong   rflags;
+        ulong   cs;
+        ulong   fs;
+        ulong   gs;
+    }
+
+    struct x86_state_hdr_t
+    {
+        int     flavor;
+        int     count;
+    }
+
+    struct x86_thread_state_t
+    {
+        x86_state_hdr_t             tsh;
+        union _uts
+        {
+            x86_thread_state32_t    ts32;
+            x86_thread_state64_t    ts64;
+        }
+        _uts                        uts;
+    }
+
+    enum : mach_msg_type_number_t
+    {
+        x86_THREAD_STATE32_COUNT = cast(mach_msg_type_number_t)( x86_thread_state32_t.sizeof / int.sizeof ),
+        x86_THREAD_STATE64_COUNT = cast(mach_msg_type_number_t)( x86_thread_state64_t.sizeof / int.sizeof ),
+        x86_THREAD_STATE_COUNT   = cast(mach_msg_type_number_t)( x86_thread_state_t.sizeof / int.sizeof ),
+    }
+
+    alias x86_THREAD_STATE          MACHINE_THREAD_STATE;
+    alias x86_THREAD_STATE_COUNT    MACHINE_THREAD_STATE_COUNT;
+
+    mach_port_t   mach_thread_self();
+    kern_return_t thread_suspend(thread_act_t);
+    kern_return_t thread_resume(thread_act_t);
+    kern_return_t thread_get_state(thread_act_t, thread_state_flavor_t, thread_state_t*, mach_msg_type_number_t*);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/arpa/inet.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,132 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.arpa.inet;
+
+private import core.sys.posix.config;
+public import core.stdc.inttypes; // for uint32_t, uint16_t
+public import core.sys.posix.sys.socket; // for socklen_t
+
+extern (C):
+
+//
+// Required
+//
+/*
+in_port_t // from core.sys.posix.netinet.in_
+in_addr_t // from core.sys.posix.netinet.in_
+
+struct in_addr  // from core.sys.posix.netinet.in_
+INET_ADDRSTRLEN // from core.sys.posix.netinet.in_
+
+uint32_t // from core.stdc.inttypes
+uint16_t // from core.stdc.inttypes
+
+uint32_t htonl(uint32_t);
+uint16_t htons(uint16_t);
+uint32_t ntohl(uint32_t);
+uint16_t ntohs(uint16_t);
+
+in_addr_t inet_addr(in char*);
+char*     inet_ntoa(in_addr);
+// per spec: const char* inet_ntop(int, const void*, char*, socklen_t);
+char*     inet_ntop(int, in void*, char*, socklen_t);
+int       inet_pton(int, in char*, void*);
+*/
+
+version( linux )
+{
+    alias uint16_t in_port_t;
+    alias uint32_t in_addr_t;
+
+    struct in_addr
+    {
+        in_addr_t s_addr;
+    }
+
+    enum INET_ADDRSTRLEN = 16;
+
+    uint32_t htonl(uint32_t);
+    uint16_t htons(uint16_t);
+    uint32_t ntohl(uint32_t);
+    uint16_t ntohs(uint16_t);
+
+    in_addr_t inet_addr(in char*);
+    char*     inet_ntoa(in_addr);
+    char*     inet_ntop(int, in void*, char*, socklen_t);
+    int       inet_pton(int, in char*, void*);
+}
+else version( OSX )
+{
+    alias uint16_t in_port_t; // TODO: verify
+    alias uint32_t in_addr_t; // TODO: verify
+
+    struct in_addr
+    {
+        in_addr_t s_addr;
+    }
+
+    enum INET_ADDRSTRLEN = 16;
+
+    uint32_t htonl(uint32_t);
+    uint16_t htons(uint16_t);
+    uint32_t ntohl(uint32_t);
+    uint16_t ntohs(uint16_t);
+
+    in_addr_t inet_addr(in char*);
+    char*     inet_ntoa(in_addr);
+    char*     inet_ntop(int, in void*, char*, socklen_t);
+    int       inet_pton(int, in char*, void*);
+}
+else version( freebsd )
+{
+    alias uint16_t in_port_t; // TODO: verify
+    alias uint32_t in_addr_t; // TODO: verify
+
+    struct in_addr
+    {
+        in_addr_t s_addr;
+    }
+
+    enum INET_ADDRSTRLEN = 16;
+
+    uint32_t htonl(uint32_t);
+    uint16_t htons(uint16_t);
+    uint32_t ntohl(uint32_t);
+    uint16_t ntohs(uint16_t);
+
+    in_addr_t inet_addr(in char*);
+    char*     inet_ntoa(in_addr);
+    char*     inet_ntop(int, in void*, char*, socklen_t);
+    int       inet_pton(int, in char*, void*);
+}
+
+//
+// IPV6 (IP6)
+//
+/*
+INET6_ADDRSTRLEN // from core.sys.posix.netinet.in_
+*/
+
+version( linux )
+{
+    enum INET6_ADDRSTRLEN = 46;
+}
+else version( OSX )
+{
+    enum INET6_ADDRSTRLEN = 46;
+}
+else version( freebsd )
+{
+    enum INET6_ADDRSTRLEN = 46;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/config.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,32 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.config;
+
+public import core.stdc.config;
+
+extern (C):
+
+version( linux )
+{
+  version( X86_64 )
+  {
+    enum bool  __USE_LARGEFILE64    = true;
+  }
+  else
+  {
+    enum bool  __USE_LARGEFILE64    = false;
+  }
+    enum bool  __USE_FILE_OFFSET64  = __USE_LARGEFILE64;
+    enum bool  __REDIRECT           = false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/dirent.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,203 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.dirent;
+
+private import core.sys.posix.config;
+public import core.sys.posix.sys.types; // for ino_t
+
+extern (C):
+
+//
+// Required
+//
+/*
+DIR
+
+struct dirent
+{
+    char[] d_name;
+}
+
+int     closedir(DIR*);
+DIR*    opendir(in char*);
+dirent* readdir(DIR*);
+void    rewinddir(DIR*);
+*/
+
+version( linux )
+{
+    // NOTE: The following constants are non-standard Linux definitions
+    //       for dirent.d_type.
+    enum
+    {
+        DT_UNKNOWN  = 0,
+        DT_FIFO     = 1,
+        DT_CHR      = 2,
+        DT_DIR      = 4,
+        DT_BLK      = 6,
+        DT_REG      = 8,
+        DT_LNK      = 10,
+        DT_SOCK     = 12,
+        DT_WHT      = 14
+    }
+
+    struct dirent
+    {
+        ino_t       d_ino;
+        off_t       d_off;
+        ushort      d_reclen;
+        ubyte       d_type;
+        char[256]   d_name;
+    }
+
+    struct DIR
+    {
+        // Managed by OS
+    }
+
+    static if( __USE_LARGEFILE64 )
+    {
+        dirent* readdir64(DIR*);
+        alias   readdir64 readdir;
+    }
+    else
+    {
+        dirent* readdir(DIR*);
+    }
+}
+else version( OSX )
+{
+    enum
+    {
+        DT_UNKNOWN  = 0,
+        DT_FIFO     = 1,
+        DT_CHR      = 2,
+        DT_DIR      = 4,
+        DT_BLK      = 6,
+        DT_REG      = 8,
+        DT_LNK      = 10,
+        DT_SOCK     = 12,
+        DT_WHT      = 14
+    }
+
+    align(4)
+    struct dirent
+    {
+        ino_t       d_ino;
+        ushort      d_reclen;
+        ubyte       d_type;
+        ubyte       d_namlen;
+        char[256]   d_name;
+    }
+
+    struct DIR
+    {
+        // Managed by OS
+    }
+
+    dirent* readdir(DIR*);
+}
+else version( freebsd )
+{
+    enum
+    {
+        DT_UNKNOWN  = 0,
+        DT_FIFO     = 1,
+        DT_CHR      = 2,
+        DT_DIR      = 4,
+        DT_BLK      = 6,
+        DT_REG      = 8,
+        DT_LNK      = 10,
+        DT_SOCK     = 12,
+        DT_WHT      = 14
+    }
+
+    align(4)
+    struct dirent
+    {
+        uint      d_fileno;
+        ushort    d_reclen;
+        ubyte     d_type;
+        ubyte     d_namelen;
+        char[256] d_name;
+    }
+
+    struct _telldir;
+    struct DIR
+    {
+        int       dd_fd;
+        c_long    dd_loc;
+        c_long    dd_size;
+        char*     dd_buf;
+        int       dd_len;
+        c_long    dd_seek;
+        c_long    dd_rewind;
+        int       dd_flags;
+        void*     dd_lock;
+        _telldir* dd_td;
+    }
+
+    dirent* readdir(DIR*);
+}
+else
+{
+    dirent* readdir(DIR*);
+}
+
+int     closedir(DIR*);
+DIR*    opendir(in char*);
+//dirent* readdir(DIR*);
+void    rewinddir(DIR*);
+
+//
+// Thread-Safe Functions (TSF)
+//
+/*
+int readdir_r(DIR*, dirent*, dirent**);
+*/
+
+version( linux )
+{
+  static if( __USE_LARGEFILE64 )
+  {
+    int   readdir64_r(DIR*, dirent*, dirent**);
+    alias readdir64_r readdir_r;
+  }
+  else
+  {
+    int readdir_r(DIR*, dirent*, dirent**);
+  }
+}
+else version( OSX )
+{
+    int readdir_r(DIR*, dirent*, dirent**);
+}
+else version( freebsd )
+{
+    int readdir_r(DIR*, dirent*, dirent**);
+}
+
+//
+// XOpen (XSI)
+//
+/*
+void   seekdir(DIR*, c_long);
+c_long telldir(DIR*);
+*/
+
+version( linux )
+{
+    void   seekdir(DIR*, c_long);
+    c_long telldir(DIR*);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/dlfcn.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,70 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.dlfcn;
+
+private import core.sys.posix.config;
+
+extern (C):
+
+//
+// XOpen (XSI)
+//
+/*
+RTLD_LAZY
+RTLD_NOW
+RTLD_GLOBAL
+RTLD_LOCAL
+
+int   dlclose(void*);
+char* dlerror();
+void* dlopen(in char*, int);
+void* dlsym(void*, in char*);
+*/
+
+version( linux )
+{
+    enum RTLD_LAZY      = 0x00001;
+    enum RTLD_NOW       = 0x00002;
+    enum RTLD_GLOBAL    = 0x00100;
+    enum RTLD_LOCAL     = 0x00000;
+
+    int   dlclose(void*);
+    char* dlerror();
+    void* dlopen(in char*, int);
+    void* dlsym(void*, in char*);
+}
+else version( OSX )
+{
+    enum RTLD_LAZY      = 0x00001;
+    enum RTLD_NOW       = 0x00002;
+    enum RTLD_GLOBAL    = 0x00100;
+    enum RTLD_LOCAL     = 0x00000;
+
+    int   dlclose(void*);
+    char* dlerror();
+    void* dlopen(in char*, int);
+    void* dlsym(void*, in char*);
+}
+else version( freebsd )
+{
+    enum RTLD_LAZY      = 1;
+    enum RTLD_NOW       = 2;
+    enum RTLD_GLOBAL    = 0x100;
+    enum RTLD_LOCAL     = 0;
+
+    int   dlclose(void*);
+    char* dlerror();
+    void* dlopen(in char*, int);
+    void* dlsym(void*, in char*);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/fcntl.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,253 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.fcntl;
+
+private import core.sys.posix.config;
+private import core.stdc.stdint;
+public import core.stdc.stddef;          // for size_t
+public import core.sys.posix.sys.types; // for off_t, mode_t
+public import core.sys.posix.sys.stat;  // for S_IFMT, etc.
+
+extern (C):
+
+//
+// Required
+//
+/*
+F_DUPFD
+F_GETFD
+F_SETFD
+F_GETFL
+F_SETFL
+F_GETLK
+F_SETLK
+F_SETLKW
+F_GETOWN
+F_SETOWN
+
+FD_CLOEXEC
+
+F_RDLCK
+F_UNLCK
+F_WRLCK
+
+O_CREAT
+O_EXCL
+O_NOCTTY
+O_TRUNC
+
+O_APPEND
+O_DSYNC
+O_NONBLOCK
+O_RSYNC
+O_SYNC
+
+O_ACCMODE
+O_RDONLY
+O_RDWR
+O_WRONLY
+
+struct flock
+{
+    short   l_type;
+    short   l_whence;
+    off_t   l_start;
+    off_t   l_len;
+    pid_t   l_pid;
+}
+
+int creat(in char*, mode_t);
+int fcntl(int, int, ...);
+int open(in char*, int, ...);
+*/
+version( linux )
+{
+    enum F_DUPFD        = 0;
+    enum F_GETFD        = 1;
+    enum F_SETFD        = 2;
+    enum F_GETFL        = 3;
+    enum F_SETFL        = 4;
+  static if( __USE_FILE_OFFSET64 )
+  {
+    enum F_GETLK        = 12;
+    enum F_SETLK        = 13;
+    enum F_SETLKW       = 14;
+  }
+  else
+  {
+    enum F_GETLK        = 5;
+    enum F_SETLK        = 6;
+    enum F_SETLKW       = 7;
+  }
+    enum F_GETOWN       = 9;
+    enum F_SETOWN       = 8;
+
+    enum FD_CLOEXEC     = 1;
+
+    enum F_RDLCK        = 0;
+    enum F_UNLCK        = 2;
+    enum F_WRLCK        = 1;
+
+    enum O_CREAT        = 0100;
+    enum O_EXCL         = 0200;
+    enum O_NOCTTY       = 0400;
+    enum O_TRUNC        = 01000;
+
+    enum O_APPEND       = 02000;
+    enum O_NONBLOCK     = 04000;
+    enum O_SYNC         = 010000;
+    enum O_DSYNC        = O_SYNC;
+    enum O_RSYNC        = O_SYNC;
+
+    enum O_ACCMODE      = 0003;
+    enum O_RDONLY       = 00;
+    enum O_WRONLY       = 01;
+    enum O_RDWR         = 02;
+
+    struct flock
+    {
+        short   l_type;
+        short   l_whence;
+        off_t   l_start;
+        off_t   l_len;
+        pid_t   l_pid;
+    }
+
+    static if( __USE_LARGEFILE64 )
+    {
+        int   creat64(in char*, mode_t);
+        alias creat64 creat;
+
+        int   open64(in char*, int, ...);
+        alias open64 open;
+    }
+    else
+    {
+        int   creat(in char*, mode_t);
+        int   open(in char*, int, ...);
+    }
+}
+else version( OSX )
+{
+    enum F_DUPFD        = 0;
+    enum F_GETFD        = 1;
+    enum F_SETFD        = 2;
+    enum F_GETFL        = 3;
+    enum F_SETFL        = 4;
+    enum F_GETOWN       = 5;
+    enum F_SETOWN       = 6;
+    enum F_GETLK        = 7;
+    enum F_SETLK        = 8;
+    enum F_SETLKW       = 9;
+
+    enum FD_CLOEXEC     = 1;
+
+    enum F_RDLCK        = 1;
+    enum F_UNLCK        = 2;
+    enum F_WRLCK        = 3;
+
+    enum O_CREAT        = 0x0200;
+    enum O_EXCL         = 0x0800;
+    enum O_NOCTTY       = 0;
+    enum O_TRUNC        = 0x0400;
+
+    enum O_RDONLY       = 0x0000;
+    enum O_WRONLY       = 0x0001;
+    enum O_RDWR         = 0x0002;
+    enum O_ACCMODE      = 0x0003;
+
+    enum O_NONBLOCK     = 0x0004;
+    enum O_APPEND       = 0x0008;
+    enum O_SYNC         = 0x0080;
+    //enum O_DSYNC
+    //enum O_RSYNC
+
+    struct flock
+    {
+        off_t   l_start;
+        off_t   l_len;
+        pid_t   l_pid;
+        short   l_type;
+        short   l_whence;
+    }
+
+    int creat(in char*, mode_t);
+    int open(in char*, int, ...);
+}
+else version( freebsd )
+{
+    enum F_DUPFD        = 0;
+    enum F_GETFD        = 1;
+    enum F_SETFD        = 2;
+    enum F_GETFL        = 3;
+    enum F_SETFL        = 4;
+    enum F_GETOWN       = 5;
+    enum F_SETOWN       = 6;
+    enum F_GETLK        = 7;
+    enum F_SETLK        = 8;
+    enum F_SETLKW       = 9;
+
+    enum FD_CLOEXEC     = 1;
+
+    enum F_RDLCK        = 1;
+    enum F_UNLCK        = 2;
+    enum F_WRLCK        = 3;
+
+    enum O_CREAT        = 0x0200;
+    enum O_EXCL         = 0x0800;
+    enum O_NOCTTY       = 0;
+    enum O_TRUNC        = 0x0400;
+
+    enum O_RDONLY       = 0x0000;
+    enum O_WRONLY       = 0x0001;
+    enum O_RDWR         = 0x0002;
+    enum O_ACCMODE      = 0x0003;
+
+    enum O_NONBLOCK     = 0x0004;
+    enum O_APPEND       = 0x0008;
+    enum O_SYNC         = 0x0080;
+    //enum O_DSYNC
+    //enum O_RSYNC
+
+    struct flock
+    {
+        off_t   l_start;
+        off_t   l_len;
+        pid_t   l_pid;
+        short   l_type;
+        short   l_whence;
+    }
+
+    int creat(in char*, mode_t);
+    int open(in char*, int, ...);
+}
+
+//int creat(in char*, mode_t);
+int fcntl(int, int, ...);
+//int open(in char*, int, ...);
+
+//
+// Advisory Information (ADV)
+//
+/*
+POSIX_FADV_NORMAL
+POSIX_FADV_SEQUENTIAL
+POSIX_FADV_RANDOM
+POSIX_FADV_WILLNEED
+POSIX_FADV_DONTNEED
+POSIX_FADV_NOREUSE
+
+int posix_fadvise(int, off_t, off_t, int);
+int posix_fallocate(int, off_t, off_t);
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/inttypes.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,35 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.inttypes;
+
+private import core.sys.posix.config;
+public import core.stdc.inttypes;
+
+//
+// Required
+//
+/*
+intmax_t  imaxabs(intmax_t);
+imaxdiv_t imaxdiv(intmax_t, intmax_t);
+intmax_t  strtoimax(in char*, char**, int);
+uintmax_t strtoumax(in char *, char**, int);
+intmax_t  wcstoimax(in wchar_t*, wchar_t**, int);
+uintmax_t wcstoumax(in wchar_t*, wchar_t**, int);
+*/
+intmax_t  imaxabs(intmax_t);
+imaxdiv_t imaxdiv(intmax_t, intmax_t);
+intmax_t  strtoimax(in char*, char**, int);
+uintmax_t strtoumax(in char *, char**, int);
+intmax_t  wcstoimax(in wchar_t*, wchar_t**, int);
+uintmax_t wcstoumax(in wchar_t*, wchar_t**, int);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/net/if_.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,82 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.net.if_;
+
+private import core.sys.posix.config;
+
+extern (C):
+
+//
+// Required
+//
+/*
+struct if_nameindex // renamed to if_nameindex_t
+{
+    uint    if_index;
+    char*   if_name;
+}
+
+IF_NAMESIZE
+
+uint            if_nametoindex(in char*);
+char*           if_indextoname(uint, char*);
+if_nameindex_t* if_nameindex();
+void            if_freenameindex(if_nameindex_t*);
+*/
+
+version( linux )
+{
+    struct if_nameindex_t
+    {
+        uint    if_index;
+        char*   if_name;
+    }
+
+    enum IF_NAMESIZE = 16;
+
+    uint            if_nametoindex(in char*);
+    char*           if_indextoname(uint, char*);
+    if_nameindex_t* if_nameindex();
+    void            if_freenameindex(if_nameindex_t*);
+}
+else version( OSX )
+{
+    struct if_nameindex_t
+    {
+        uint    if_index;
+        char*   if_name;
+    }
+
+    enum IF_NAMESIZE = 16;
+
+    uint            if_nametoindex(in char*);
+    char*           if_indextoname(uint, char*);
+    if_nameindex_t* if_nameindex();
+    void            if_freenameindex(if_nameindex_t*);
+}
+else version( freebsd )
+{
+    struct if_nameindex_t
+    {
+        uint    if_index;
+        char*   if_name;
+    }
+
+    enum IF_NAMESIZE = 16;
+
+    uint            if_nametoindex(in char*);
+    char*           if_indextoname(uint, char*);
+    if_nameindex_t* if_nameindex();
+    void            if_freenameindex(if_nameindex_t*);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/netinet/in_.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,464 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.netinet.in_;
+
+private import core.sys.posix.config;
+public import core.stdc.inttypes; // for uint32_t, uint16_t, uint8_t
+public import core.sys.posix.arpa.inet;
+public import core.sys.posix.sys.socket; // for sa_family_t
+
+extern (C):
+
+//
+// Required
+//
+/*
+NOTE: The following must must be defined in core.sys.posix.arpa.inet to break
+      a circular import: in_port_t, in_addr_t, struct in_addr, INET_ADDRSTRLEN.
+
+in_port_t
+in_addr_t
+
+sa_family_t // from core.sys.posix.sys.socket
+uint8_t     // from core.stdc.inttypes
+uint32_t    // from core.stdc.inttypes
+
+struct in_addr
+{
+    in_addr_t   s_addr;
+}
+
+struct sockaddr_in
+{
+    sa_family_t sin_family;
+    in_port_t   sin_port;
+    in_addr     sin_addr;
+}
+
+IPPROTO_IP
+IPPROTO_ICMP
+IPPROTO_TCP
+IPPROTO_UDP
+
+INADDR_ANY
+INADDR_BROADCAST
+
+INET_ADDRSTRLEN
+
+htonl() // from core.sys.posix.arpa.inet
+htons() // from core.sys.posix.arpa.inet
+ntohl() // from core.sys.posix.arpa.inet
+ntohs() // from core.sys.posix.arpa.inet
+*/
+
+version( linux )
+{
+    private enum __SOCK_SIZE__ = 16;
+
+    struct sockaddr_in
+    {
+        sa_family_t sin_family;
+        in_port_t   sin_port;
+        in_addr     sin_addr;
+
+        /* Pad to size of `struct sockaddr'. */
+        ubyte[__SOCK_SIZE__ - sa_family_t.sizeof -
+              in_port_t.sizeof - in_addr.sizeof] __pad;
+    }
+
+    enum
+    {
+        IPPROTO_IP   = 0,
+        IPPROTO_ICMP = 1,
+        IPPROTO_TCP  = 6,
+        IPPROTO_UDP  = 17
+    }
+
+    enum uint INADDR_ANY       = 0x00000000;
+    enum uint INADDR_BROADCAST = 0xffffffff;
+    
+    enum INET_ADDRSTRLEN       = 16;
+}
+else version( OSX )
+{
+    private enum __SOCK_SIZE__ = 16;
+
+    struct sockaddr_in
+    {
+        ubyte       sin_len;
+        sa_family_t sin_family;
+        in_port_t   sin_port;
+        in_addr     sin_addr;
+        ubyte[8]    sin_zero;
+    }
+
+    enum
+    {
+        IPPROTO_IP   = 0,
+        IPPROTO_ICMP = 1,
+        IPPROTO_TCP  = 6,
+        IPPROTO_UDP  = 17
+    }
+
+    enum uint INADDR_ANY       = 0x00000000;
+    enum uint INADDR_BROADCAST = 0xffffffff;
+    
+    enum INET_ADDRSTRLEN       = 16;
+}
+else version( freebsd )
+{
+    private enum __SOCK_SIZE__ = 16;
+
+    struct sockaddr_in
+    {
+        ubyte       sin_len;
+        sa_family_t sin_family;
+        in_port_t   sin_port;
+        in_addr     sin_addr;
+        ubyte[8]    sin_zero;
+    }
+
+    enum
+    {
+        IPPROTO_IP   = 0,
+        IPPROTO_ICMP = 1,
+        IPPROTO_TCP  = 6,
+        IPPROTO_UDP  = 17
+    }
+
+    enum uint INADDR_ANY       = 0x00000000;
+    enum uint INADDR_BROADCAST = 0xffffffff;
+}
+
+
+//
+// IPV6 (IP6)
+//
+/*
+NOTE: The following must must be defined in core.sys.posix.arpa.inet to break
+      a circular import: INET6_ADDRSTRLEN.
+
+struct in6_addr
+{
+    uint8_t[16] s6_addr;
+}
+
+struct sockaddr_in6
+{
+    sa_family_t sin6_family;
+    in_port_t   sin6_port;
+    uint32_t    sin6_flowinfo;
+    in6_addr    sin6_addr;
+    uint32_t    sin6_scope_id;
+}
+
+extern in6_addr in6addr_any;
+extern in6_addr in6addr_loopback;
+
+struct ipv6_mreq
+{
+    in6_addr    ipv6mr_multiaddr;
+    uint        ipv6mr_interface;
+}
+
+IPPROTO_IPV6
+
+INET6_ADDRSTRLEN
+
+IPV6_JOIN_GROUP
+IPV6_LEAVE_GROUP
+IPV6_MULTICAST_HOPS
+IPV6_MULTICAST_IF
+IPV6_MULTICAST_LOOP
+IPV6_UNICAST_HOPS
+IPV6_V6ONLY
+
+// macros
+int IN6_IS_ADDR_UNSPECIFIED(in6_addr*)
+int IN6_IS_ADDR_LOOPBACK(in6_addr*)
+int IN6_IS_ADDR_MULTICAST(in6_addr*)
+int IN6_IS_ADDR_LINKLOCAL(in6_addr*)
+int IN6_IS_ADDR_SITELOCAL(in6_addr*)
+int IN6_IS_ADDR_V4MAPPED(in6_addr*)
+int IN6_IS_ADDR_V4COMPAT(in6_addr*)
+int IN6_IS_ADDR_MC_NODELOCAL(in6_addr*)
+int IN6_IS_ADDR_MC_LINKLOCAL(in6_addr*)
+int IN6_IS_ADDR_MC_SITELOCAL(in6_addr*)
+int IN6_IS_ADDR_MC_ORGLOCAL(in6_addr*)
+int IN6_IS_ADDR_MC_GLOBAL(in6_addr*)
+*/
+
+version ( linux )
+{
+    struct in6_addr
+    {
+        union
+        {
+            uint8_t[16] s6_addr;
+            uint16_t[8] s6_addr16;
+            uint32_t[4] s6_addr32;
+        }
+    }
+
+    struct sockaddr_in6
+    {
+        sa_family_t sin6_family;
+        in_port_t   sin6_port;
+        uint32_t    sin6_flowinfo;
+        in6_addr    sin6_addr;
+        uint32_t    sin6_scope_id;
+    }
+
+    extern in6_addr in6addr_any;
+    extern in6_addr in6addr_loopback;
+
+    struct ipv6_mreq
+    {
+        in6_addr    ipv6mr_multiaddr;
+        uint        ipv6mr_interface;
+    }
+
+    enum : uint
+    {
+        IPPROTO_IPV6        = 41,
+
+        INET6_ADDRSTRLEN    = 46,
+
+        IPV6_JOIN_GROUP     = 20,
+        IPV6_LEAVE_GROUP    = 21,
+        IPV6_MULTICAST_HOPS = 18,
+        IPV6_MULTICAST_IF   = 17,
+        IPV6_MULTICAST_LOOP = 19,
+        IPV6_UNICAST_HOPS   = 16,
+        IPV6_V6ONLY         = 26
+    }
+
+    // macros
+    extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr )
+    {
+        return (cast(uint32_t*) addr)[0] == 0 &&
+               (cast(uint32_t*) addr)[1] == 0 &&
+               (cast(uint32_t*) addr)[2] == 0 &&
+               (cast(uint32_t*) addr)[3] == 0;
+    }
+
+    extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr )
+    {
+        return (cast(uint32_t*) addr)[0] == 0  &&
+               (cast(uint32_t*) addr)[1] == 0  &&
+               (cast(uint32_t*) addr)[2] == 0  &&
+               (cast(uint32_t*) addr)[3] == htonl( 1 );
+    }
+
+    extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr )
+    {
+        return (cast(uint8_t*) addr)[0] == 0xff;
+    }
+
+    extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr )
+    {
+        return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfe800000 );
+    }
+
+    extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr )
+    {
+        return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfec00000 );
+    }
+
+    extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr )
+    {
+        return (cast(uint32_t*) addr)[0] == 0 &&
+               (cast(uint32_t*) addr)[1] == 0 &&
+               (cast(uint32_t*) addr)[2] == htonl( 0xffff );
+    }
+
+    extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr )
+    {
+        return (cast(uint32_t*) addr)[0] == 0 &&
+               (cast(uint32_t*) addr)[1] == 0 &&
+               (cast(uint32_t*) addr)[2] == 0 &&
+               ntohl( (cast(uint32_t*) addr)[3] ) > 1;
+    }
+
+    extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr )
+    {
+        return IN6_IS_ADDR_MULTICAST( addr ) &&
+               ((cast(uint8_t*) addr)[1] & 0xf) == 0x1;
+    }
+
+    extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr )
+    {
+        return IN6_IS_ADDR_MULTICAST( addr ) &&
+               ((cast(uint8_t*) addr)[1] & 0xf) == 0x2;
+    }
+
+    extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr )
+    {
+        return IN6_IS_ADDR_MULTICAST(addr) &&
+               ((cast(uint8_t*) addr)[1] & 0xf) == 0x5;
+    }
+
+    extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr )
+    {
+        return IN6_IS_ADDR_MULTICAST( addr) &&
+               ((cast(uint8_t*) addr)[1] & 0xf) == 0x8;
+    }
+
+    extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr )
+    {
+        return IN6_IS_ADDR_MULTICAST( addr ) &&
+               ((cast(uint8_t*) addr)[1] & 0xf) == 0xe;
+    }
+}
+else version( OSX )
+{
+    struct in6_addr
+    {
+        union
+        {
+            uint8_t[16] s6_addr;
+            uint16_t[8] s6_addr16;
+            uint32_t[4] s6_addr32;
+        }
+    }
+
+    struct sockaddr_in6
+    {
+        uint8_t     sin6_len;
+        sa_family_t sin6_family;
+        in_port_t   sin6_port;
+        uint32_t    sin6_flowinfo;
+        in6_addr    sin6_addr;
+        uint32_t    sin6_scope_id;
+    }
+
+    extern in6_addr in6addr_any;
+    extern in6_addr in6addr_loopback;
+
+    struct ipv6_mreq
+    {
+        in6_addr    ipv6mr_multiaddr;
+        uint        ipv6mr_interface;
+    }
+
+    enum : uint
+    {
+        IPPROTO_IPV6        = 41,
+
+        INET6_ADDRSTRLEN    = 46,
+
+        IPV6_JOIN_GROUP     = 12,
+        IPV6_LEAVE_GROUP    = 13,
+        IPV6_MULTICAST_HOPS = 10,
+        IPV6_MULTICAST_IF   = 9,
+        IPV6_MULTICAST_LOOP = 11,
+        IPV6_UNICAST_HOPS   = 4,
+        IPV6_V6ONLY         = 27
+    }
+
+    // macros
+    extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr )
+    {
+        return (cast(uint32_t*) addr)[0] == 0 &&
+               (cast(uint32_t*) addr)[1] == 0 &&
+               (cast(uint32_t*) addr)[2] == 0 &&
+               (cast(uint32_t*) addr)[3] == 0;
+    }
+
+    extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr )
+    {
+        return (cast(uint32_t*) addr)[0] == 0  &&
+               (cast(uint32_t*) addr)[1] == 0  &&
+               (cast(uint32_t*) addr)[2] == 0  &&
+               (cast(uint32_t*) addr)[3] == ntohl( 1 );
+    }
+
+    extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr )
+    {
+        return addr.s6_addr[0] == 0xff;
+    }
+
+    extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr )
+    {
+        return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0x80;
+    }
+
+    extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr )
+    {
+        return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0xc0;
+    }
+
+    extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr )
+    {
+        return (cast(uint32_t*) addr)[0] == 0 &&
+               (cast(uint32_t*) addr)[1] == 0 &&
+               (cast(uint32_t*) addr)[2] == ntohl( 0x0000ffff );
+    }
+
+    extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr )
+    {
+        return (cast(uint32_t*) addr)[0] == 0 &&
+               (cast(uint32_t*) addr)[1] == 0 &&
+               (cast(uint32_t*) addr)[2] == 0 &&
+               (cast(uint32_t*) addr)[3] != 0 &&
+               (cast(uint32_t*) addr)[3] != ntohl( 1 );
+    }
+
+    extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr )
+    {
+        return IN6_IS_ADDR_MULTICAST( addr ) &&
+               ((cast(uint8_t*) addr)[1] & 0xf) == 0x1;
+    }
+
+    extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr )
+    {
+        return IN6_IS_ADDR_MULTICAST( addr ) &&
+               ((cast(uint8_t*) addr)[1] & 0xf) == 0x2;
+    }
+
+    extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr )
+    {
+        return IN6_IS_ADDR_MULTICAST(addr) &&
+               ((cast(uint8_t*) addr)[1] & 0xf) == 0x5;
+    }
+
+    extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr )
+    {
+        return IN6_IS_ADDR_MULTICAST( addr) &&
+               ((cast(uint8_t*) addr)[1] & 0xf) == 0x8;
+    }
+
+    extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr )
+    {
+        return IN6_IS_ADDR_MULTICAST( addr ) &&
+               ((cast(uint8_t*) addr)[1] & 0xf) == 0xe;
+    }
+}
+
+
+//
+// Raw Sockets (RS)
+//
+/*
+IPPROTO_RAW
+*/
+
+version (linux )
+{
+    enum uint IPPROTO_RAW = 255;
+}
+else version( OSX )
+{
+    enum uint IPPROTO_RAW = 255;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/netinet/tcp.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,38 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.netinet.tcp;
+
+private import core.sys.posix.config;
+
+extern (C):
+
+//
+// Required
+//
+/*
+TCP_NODELAY
+*/
+
+version( linux )
+{
+    enum TCP_NODELAY = 1;
+}
+else version( OSX )
+{
+    enum TCP_NODELAY = 1;
+}
+else version( freebsd )
+{
+    enum TCP_NODELAY = 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/poll.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,141 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.poll;
+
+private import core.sys.posix.config;
+
+extern (C):
+
+//
+// XOpen (XSI)
+//
+/*
+struct pollfd
+{
+    int     fd;
+    short   events;
+    short   revents;
+}
+
+nfds_t
+
+POLLIN
+POLLRDNORM
+POLLRDBAND
+POLLPRI
+POLLOUT
+POLLWRNORM
+POLLWRBAND
+POLLERR
+POLLHUP
+POLLNVAL
+
+int poll(pollfd[], nfds_t, int);
+*/
+
+version( linux )
+{
+    struct pollfd
+    {
+        int     fd;
+        short   events;
+        short   revents;
+    }
+
+    alias c_ulong nfds_t;
+
+    enum
+    {
+        POLLIN      = 0x001,
+        POLLRDNORM  = 0x040,
+        POLLRDBAND  = 0x080,
+        POLLPRI     = 0x002,
+        POLLOUT     = 0x004,
+        POLLWRNORM  = 0x100,
+        POLLWRBAND  = 0x200,
+        POLLERR     = 0x008,
+        POLLHUP     = 0x010,
+        POLLNVAL    = 0x020,
+    }
+
+    int poll(pollfd*, nfds_t, int);
+}
+else version( OSX )
+{
+    struct pollfd
+    {
+        int     fd;
+        short   events;
+        short   revents;
+    };
+
+    alias uint nfds_t;
+
+    enum
+    {
+        POLLIN      = 0x0001,
+        POLLPRI     = 0x0002,
+        POLLOUT     = 0x0004,
+        POLLRDNORM  = 0x0040,
+        POLLWRNORM  = POLLOUT,
+        POLLRDBAND  = 0x0080,
+        POLLWRBAND  = 0x0100,
+        POLLEXTEND  = 0x0200,
+        POLLATTRIB  = 0x0400,
+        POLLNLINK   = 0x0800,
+        POLLWRITE   = 0x1000,
+        POLLERR     = 0x0008,
+        POLLHUP     = 0x0010,
+        POLLNVAL    = 0x0020,
+
+        POLLSTANDARD = (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|
+                        POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)
+    }
+
+    int poll(pollfd*, nfds_t, int);
+}
+else version( freebsd )
+{
+    struct pollfd
+    {
+        int     fd;
+        short   events;
+        short   revents;
+    };
+
+    alias uint nfds_t;
+
+    enum
+    {
+        POLLIN      = 0x0001,
+        POLLPRI     = 0x0002,
+        POLLOUT     = 0x0004,
+        POLLRDNORM  = 0x0040,
+        POLLWRNORM  = POLLOUT,
+        POLLRDBAND  = 0x0080,
+        POLLWRBAND  = 0x0100,
+        //POLLEXTEND  = 0x0200,
+        //POLLATTRIB  = 0x0400,
+        //POLLNLINK   = 0x0800,
+        //POLLWRITE   = 0x1000,
+        POLLERR     = 0x0008,
+        POLLHUP     = 0x0010,
+        POLLNVAL    = 0x0020,
+
+        POLLSTANDARD = (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|
+        POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)
+    }
+
+    int poll(pollfd*, nfds_t, int);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/pthread.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,585 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.pthread;
+
+private import core.sys.posix.config;
+public import core.sys.posix.sys.types;
+public import core.sys.posix.sched;
+public import core.sys.posix.time;
+
+extern (C):
+
+//
+// Required
+//
+/*
+PTHREAD_CANCEL_ASYNCHRONOUS
+PTHREAD_CANCEL_ENABLE
+PTHREAD_CANCEL_DEFERRED
+PTHREAD_CANCEL_DISABLE
+PTHREAD_CANCELED
+PTHREAD_COND_INITIALIZER
+PTHREAD_CREATE_DETACHED
+PTHREAD_CREATE_JOINABLE
+PTHREAD_EXPLICIT_SCHED
+PTHREAD_INHERIT_SCHED
+PTHREAD_MUTEX_INITIALIZER
+PTHREAD_ONCE_INIT
+PTHREAD_PROCESS_SHARED
+PTHREAD_PROCESS_PRIVATE
+
+int pthread_atfork(void function(), void function(), void function());
+int pthread_attr_destroy(pthread_attr_t*);
+int pthread_attr_getdetachstate(in pthread_attr_t*, int*);
+int pthread_attr_getschedparam(in pthread_attr_t*, sched_param*);
+int pthread_attr_init(pthread_attr_t*);
+int pthread_attr_setdetachstate(pthread_attr_t*, int);
+int pthread_attr_setschedparam(in pthread_attr_t*, sched_param*);
+int pthread_cancel(pthread_t);
+void pthread_cleanup_push(void function(void*), void*);
+void pthread_cleanup_pop(int);
+int pthread_cond_broadcast(pthread_cond_t*);
+int pthread_cond_destroy(pthread_cond_t*);
+int pthread_cond_init(in pthread_cond_t*, pthread_condattr_t*);
+int pthread_cond_signal(pthread_cond_t*);
+int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, in timespec*);
+int pthread_cond_wait(pthread_cond_t*, pthread_mutex_t*);
+int pthread_condattr_destroy(pthread_condattr_t*);
+int pthread_condattr_init(pthread_condattr_t*);
+int pthread_create(pthread_t*, in pthread_attr_t*, void* function(void*), void*);
+int pthread_detach(pthread_t);
+int pthread_equal(pthread_t, pthread_t);
+void pthread_exit(void*);
+void* pthread_getspecific(pthread_key_t);
+int pthread_join(pthread_t, void**);
+int pthread_key_create(pthread_key_t*, void function(void*));
+int pthread_key_delete(pthread_key_t);
+int pthread_mutex_destroy(pthread_mutex_t*);
+int pthread_mutex_init(pthread_mutex_t*, pthread_mutexattr_t*);
+int pthread_mutex_lock(pthread_mutex_t*);
+int pthread_mutex_trylock(pthread_mutex_t*);
+int pthread_mutex_unlock(pthread_mutex_t*);
+int pthread_mutexattr_destroy(pthread_mutexattr_t*);
+int pthread_mutexattr_init(pthread_mutexattr_t*);
+int pthread_once(pthread_once_t*, void function());
+int pthread_rwlock_destroy(pthread_rwlock_t*);
+int pthread_rwlock_init(in pthread_rwlock_t*, pthread_rwlockattr_t*);
+int pthread_rwlock_rdlock(pthread_rwlock_t*);
+int pthread_rwlock_tryrdlock(pthread_rwlock_t*);
+int pthread_rwlock_trywrlock(pthread_rwlock_t*);
+int pthread_rwlock_unlock(pthread_rwlock_t*);
+int pthread_rwlock_wrlock(pthread_rwlock_t*);
+int pthread_rwlockattr_destroy(pthread_rwlockattr_t*);
+int pthread_rwlockattr_init(pthread_rwlockattr_t*);
+pthread_t pthread_self();
+int pthread_setcancelstate(int, int*);
+int pthread_setcanceltype(int, int*);
+int pthread_setspecific(pthread_key_t, in void*);
+void pthread_testcancel();
+*/
+version( linux )
+{
+    enum
+    {
+        PTHREAD_CANCEL_ENABLE,
+        PTHREAD_CANCEL_DISABLE
+    }
+
+    enum
+    {
+        PTHREAD_CANCEL_DEFERRED,
+        PTHREAD_CANCEL_ASYNCHRONOUS
+    }
+
+    enum PTHREAD_CANCELED = cast(void*) -1;
+
+    //enum pthread_mutex_t PTHREAD_COND_INITIALIZER = { __LOCK_ALT_INITIALIZER, 0, "", 0 };
+
+    enum
+    {
+        PTHREAD_CREATE_JOINABLE,
+        PTHREAD_CREATE_DETACHED
+    }
+
+    enum
+    {
+        PTHREAD_INHERIT_SCHED,
+        PTHREAD_EXPLICIT_SCHED
+    }
+
+    //enum pthread_mutex_t PTHREAD_MUTEX_INITIALIZER = { 0, 0, null, PTHREAD_MUTEX_NORMAL, { 0, 0 } };
+
+    enum PTHREAD_ONCE_INIT = 0;
+
+    enum
+    {
+        PTHREAD_PROCESS_PRIVATE,
+        PTHREAD_PROCESS_SHARED
+    }
+}
+else version( OSX )
+{
+    enum
+    {
+        PTHREAD_CANCEL_ENABLE   = 1,
+        PTHREAD_CANCEL_DISABLE  = 0
+    }
+
+    enum
+    {
+        PTHREAD_CANCEL_DEFERRED     = 2,
+        PTHREAD_CANCEL_ASYNCHRONOUS = 0
+    }
+
+    enum PTHREAD_CANCELED = cast(void*) -1;
+
+    //enum pthread_mutex_t PTHREAD_COND_INITIALIZER = { __LOCK_ALT_INITIALIZER, 0, "", 0 };
+
+    enum
+    {
+        PTHREAD_CREATE_JOINABLE = 1,
+        PTHREAD_CREATE_DETACHED = 2
+    }
+
+    enum
+    {
+        PTHREAD_INHERIT_SCHED   = 1,
+        PTHREAD_EXPLICIT_SCHED  = 2
+    }
+
+    //enum pthread_mutex_t PTHREAD_MUTEX_INITIALIZER = { 0, 0, null, PTHREAD_MUTEX_NORMAL, { 0, 0 } };
+
+    enum PTHREAD_ONCE_INIT = 0;
+
+    enum
+    {
+        PTHREAD_PROCESS_PRIVATE = 2,
+        PTHREAD_PROCESS_SHARED  = 1
+    }
+}
+
+int pthread_atfork(void function(), void function(), void function());
+int pthread_attr_destroy(pthread_attr_t*);
+int pthread_attr_getdetachstate(in pthread_attr_t*, int*);
+int pthread_attr_getschedparam(in pthread_attr_t*, sched_param*);
+int pthread_attr_init(pthread_attr_t*);
+int pthread_attr_setdetachstate(pthread_attr_t*, int);
+int pthread_attr_setschedparam(in pthread_attr_t*, sched_param*);
+int pthread_cancel(pthread_t);
+
+version( linux )
+{
+    alias void function(void*) _pthread_cleanup_routine;
+
+    struct _pthread_cleanup_buffer
+    {
+        _pthread_cleanup_routine    __routine;
+        void*                       __arg;
+        int                         __canceltype;
+        _pthread_cleanup_buffer*    __prev;
+    }
+
+    void _pthread_cleanup_push(_pthread_cleanup_buffer*, _pthread_cleanup_routine, void*);
+    void _pthread_cleanup_pop(_pthread_cleanup_buffer*, int);
+
+    struct pthread_cleanup
+    {
+        _pthread_cleanup_buffer buffer = void;
+
+        void push()( _pthread_cleanup_routine routine, void* arg )
+        {
+            _pthread_cleanup_push( &buffer, routine, arg );
+        }
+
+        void pop()( int execute )
+        {
+            _pthread_cleanup_pop( &buffer, execute );
+        }
+    }
+}
+else version( OSX )
+{
+    alias void function(void*) _pthread_cleanup_routine;
+
+    struct _pthread_cleanup_buffer
+    {
+        _pthread_cleanup_routine    __routine;
+        void*                       __arg;
+        _pthread_cleanup_buffer*    __next;
+    }
+
+    struct pthread_cleanup
+    {
+        _pthread_cleanup_buffer buffer = void;
+
+        void push()( _pthread_cleanup_routine routine, void* arg )
+        {
+            pthread_t self       = pthread_self();
+            buffer.__routine     = routine;
+            buffer.__arg         = arg;
+            buffer.__next        = cast(_pthread_cleanup_buffer*) self.__cleanup_stack;
+            self.__cleanup_stack = cast(pthread_handler_rec*) &buffer;
+        }
+
+        void pop()( int execute )
+        {
+            pthread_t self       = pthread_self();
+            self.__cleanup_stack = cast(pthread_handler_rec*) buffer.__next;
+            if( execute )
+            {
+                buffer.__routine( buffer.__arg );
+            }
+        }
+    }
+}
+else
+{
+    void pthread_cleanup_push(void function(void*), void*);
+    void pthread_cleanup_pop(int);
+}
+
+int pthread_cond_broadcast(pthread_cond_t*);
+int pthread_cond_destroy(pthread_cond_t*);
+int pthread_cond_init(in pthread_cond_t*, pthread_condattr_t*);
+int pthread_cond_signal(pthread_cond_t*);
+int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, in timespec*);
+int pthread_cond_wait(pthread_cond_t*, pthread_mutex_t*);
+int pthread_condattr_destroy(pthread_condattr_t*);
+int pthread_condattr_init(pthread_condattr_t*);
+int pthread_create(pthread_t*, in pthread_attr_t*, void* function(void*), void*);
+int pthread_detach(pthread_t);
+int pthread_equal(pthread_t, pthread_t);
+void pthread_exit(void*);
+void* pthread_getspecific(pthread_key_t);
+int pthread_join(pthread_t, void**);
+int pthread_key_create(pthread_key_t*, void function(void*));
+int pthread_key_delete(pthread_key_t);
+int pthread_mutex_destroy(pthread_mutex_t*);
+int pthread_mutex_init(pthread_mutex_t*, pthread_mutexattr_t*);
+int pthread_mutex_lock(pthread_mutex_t*);
+int pthread_mutex_trylock(pthread_mutex_t*);
+int pthread_mutex_unlock(pthread_mutex_t*);
+int pthread_mutexattr_destroy(pthread_mutexattr_t*);
+int pthread_mutexattr_init(pthread_mutexattr_t*);
+int pthread_once(pthread_once_t*, void function());
+int pthread_rwlock_destroy(pthread_rwlock_t*);
+int pthread_rwlock_init(in pthread_rwlock_t*, pthread_rwlockattr_t*);
+int pthread_rwlock_rdlock(pthread_rwlock_t*);
+int pthread_rwlock_tryrdlock(pthread_rwlock_t*);
+int pthread_rwlock_trywrlock(pthread_rwlock_t*);
+int pthread_rwlock_unlock(pthread_rwlock_t*);
+int pthread_rwlock_wrlock(pthread_rwlock_t*);
+int pthread_rwlockattr_destroy(pthread_rwlockattr_t*);
+int pthread_rwlockattr_init(pthread_rwlockattr_t*);
+pthread_t pthread_self();
+int pthread_setcancelstate(int, int*);
+int pthread_setcanceltype(int, int*);
+int pthread_setspecific(pthread_key_t, in void*);
+void pthread_testcancel();
+
+//
+// Barrier (BAR)
+//
+/*
+PTHREAD_BARRIER_SERIAL_THREAD
+
+int pthread_barrier_destroy(pthread_barrier_t*);
+int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint);
+int pthread_barrier_wait(pthread_barrier_t*);
+int pthread_barrierattr_destroy(pthread_barrierattr_t*);
+int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*); (BAR|TSH)
+int pthread_barrierattr_init(pthread_barrierattr_t*);
+int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int); (BAR|TSH)
+*/
+
+version( linux )
+{
+    enum PTHREAD_BARRIER_SERIAL_THREAD = -1;
+
+    int pthread_barrier_destroy(pthread_barrier_t*);
+    int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint);
+    int pthread_barrier_wait(pthread_barrier_t*);
+    int pthread_barrierattr_destroy(pthread_barrierattr_t*);
+    int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
+    int pthread_barrierattr_init(pthread_barrierattr_t*);
+    int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
+}
+
+//
+// Clock (CS)
+//
+/*
+int pthread_condattr_getclock(in pthread_condattr_t*, clockid_t*);
+int pthread_condattr_setclock(pthread_condattr_t*, clockid_t);
+*/
+
+//
+// Spinlock (SPI)
+//
+/*
+int pthread_spin_destroy(pthread_spinlock_t*);
+int pthread_spin_init(pthread_spinlock_t*, int);
+int pthread_spin_lock(pthread_spinlock_t*);
+int pthread_spin_trylock(pthread_spinlock_t*);
+int pthread_spin_unlock(pthread_spinlock_t*);
+*/
+
+version( linux )
+{
+    int pthread_spin_destroy(pthread_spinlock_t*);
+    int pthread_spin_init(pthread_spinlock_t*, int);
+    int pthread_spin_lock(pthread_spinlock_t*);
+    int pthread_spin_trylock(pthread_spinlock_t*);
+    int pthread_spin_unlock(pthread_spinlock_t*);
+}
+
+//
+// XOpen (XSI)
+//
+/*
+PTHREAD_MUTEX_DEFAULT
+PTHREAD_MUTEX_ERRORCHECK
+PTHREAD_MUTEX_NORMAL
+PTHREAD_MUTEX_RECURSIVE
+
+int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+int pthread_attr_setguardsize(pthread_attr_t*, size_t);
+int pthread_getconcurrency();
+int pthread_mutexattr_gettype(in pthread_mutexattr_t*, int*);
+int pthread_mutexattr_settype(pthread_mutexattr_t*, int);
+int pthread_setconcurrency(int);
+*/
+
+version( linux )
+{
+    enum PTHREAD_MUTEX_NORMAL       = 0;
+    enum PTHREAD_MUTEX_RECURSIVE    = 1;
+    enum PTHREAD_MUTEX_ERRORCHECK   = 2;
+    enum PTHREAD_MUTEX_DEFAULT      = PTHREAD_MUTEX_NORMAL;
+
+    int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+    int pthread_attr_setguardsize(pthread_attr_t*, size_t);
+    int pthread_getconcurrency();
+    int pthread_mutexattr_gettype(in pthread_mutexattr_t*, int*);
+    int pthread_mutexattr_settype(pthread_mutexattr_t*, int);
+    int pthread_setconcurrency(int);
+}
+else version( OSX )
+{
+    enum PTHREAD_MUTEX_NORMAL       = 0;
+    enum PTHREAD_MUTEX_ERRORCHECK   = 1;
+    enum PTHREAD_MUTEX_RECURSIVE    = 2;
+    enum PTHREAD_MUTEX_DEFAULT      = PTHREAD_MUTEX_NORMAL;
+
+    int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+    int pthread_attr_setguardsize(pthread_attr_t*, size_t);
+    int pthread_getconcurrency();
+    int pthread_mutexattr_gettype(in pthread_mutexattr_t*, int*);
+    int pthread_mutexattr_settype(pthread_mutexattr_t*, int);
+    int pthread_setconcurrency(int);
+}
+else version( freebsd )
+{
+    enum
+    {
+        PTHREAD_MUTEX_ERRORCHECK    = 1,
+        PTHREAD_MUTEX_RECURSIVE     = 2,
+        PTHREAD_MUTEX_NORMAL        = 3,
+        PTHREAD_MUTEX_ADAPTIVE_NP   = 4,
+        PTHREAD_MUTEX_TYPE_MAX
+    }
+    enum PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_ERRORCHECK;
+
+    int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+    int pthread_attr_setguardsize(pthread_attr_t*, size_t);
+    int pthread_getconcurrency();
+    int pthread_mutexattr_gettype(pthread_mutexattr_t*, int*);
+    int pthread_mutexattr_settype(pthread_mutexattr_t*, int);
+    int pthread_setconcurrency(int);
+}
+
+//
+// CPU Time (TCT)
+//
+/*
+int pthread_getcpuclockid(pthread_t, clockid_t*);
+*/
+
+version( linux )
+{
+    int pthread_getcpuclockid(pthread_t, clockid_t*);
+}
+
+//
+// Timeouts (TMO)
+//
+/*
+int pthread_mutex_timedlock(pthread_mutex_t*, timespec*);
+int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
+int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+*/
+
+version( linux )
+{
+    int pthread_mutex_timedlock(pthread_mutex_t*, timespec*);
+    int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
+    int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+}
+else version( OSX )
+{
+    int pthread_mutex_timedlock(pthread_mutex_t*, timespec*);
+    int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
+    int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+}
+
+//
+// Priority (TPI|TPP)
+//
+/*
+PTHREAD_PRIO_INHERIT (TPI)
+PTHREAD_PRIO_NONE (TPP|TPI)
+PTHREAD_PRIO_PROTECT (TPI)
+
+int pthread_mutex_getprioceiling(in pthread_mutex_t*, int*); (TPP)
+int pthread_mutex_setprioceiling(pthread_mutex_t*, int, int*); (TPP)
+int pthread_mutexattr_getprioceiling(pthread_mutexattr_t*, int*); (TPP)
+int pthread_mutexattr_getprotocol(in pthread_mutexattr_t*, int*); (TPI|TPP)
+int pthread_mutexattr_setprioceiling(pthread_mutexattr_t*, int); (TPP)
+int pthread_mutexattr_setprotocol(pthread_mutexattr_t*, int); (TPI|TPP)
+*/
+
+//
+// Scheduling (TPS)
+//
+/*
+PTHREAD_SCOPE_PROCESS
+PTHREAD_SCOPE_SYSTEM
+
+int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
+int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
+int pthread_attr_getscope(in pthread_attr_t*, int*);
+int pthread_attr_setinheritsched(pthread_attr_t*, int);
+int pthread_attr_setschedpolicy(pthread_attr_t*, int);
+int pthread_attr_setscope(pthread_attr_t*, int);
+int pthread_getschedparam(pthread_t, int*, sched_param*);
+int pthread_setschedparam(pthread_t, int, in sched_param*);
+int pthread_setschedprio(pthread_t, int);
+*/
+
+version( linux )
+{
+    enum
+    {
+        PTHREAD_SCOPE_SYSTEM,
+        PTHREAD_SCOPE_PROCESS
+    }
+
+    int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
+    int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
+    int pthread_attr_getscope(in pthread_attr_t*, int*);
+    int pthread_attr_setinheritsched(pthread_attr_t*, int);
+    int pthread_attr_setschedpolicy(pthread_attr_t*, int);
+    int pthread_attr_setscope(pthread_attr_t*, int);
+    int pthread_getschedparam(pthread_t, int*, sched_param*);
+    int pthread_setschedparam(pthread_t, int, in sched_param*);
+    //int pthread_setschedprio(pthread_t, int);
+}
+else version( OSX )
+{
+    enum
+    {
+        PTHREAD_SCOPE_SYSTEM    = 1,
+        PTHREAD_SCOPE_PROCESS   = 2
+    }
+
+    int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
+    int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
+    int pthread_attr_getscope(in pthread_attr_t*, int*);
+    int pthread_attr_setinheritsched(pthread_attr_t*, int);
+    int pthread_attr_setschedpolicy(pthread_attr_t*, int);
+    int pthread_attr_setscope(pthread_attr_t*, int);
+    int pthread_getschedparam(pthread_t, int*, sched_param*);
+    int pthread_setschedparam(pthread_t, int, in sched_param*);
+    //int pthread_setschedprio(pthread_t, int);
+}
+else version( freebsd )
+{
+    enum
+    {
+        PTHREAD_SCOPE_PROCESS   = 0,
+        PTHREAD_SCOPE_SYSTEM    = 0x2
+    }
+
+    int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
+    int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
+    int pthread_attr_getscope(in pthread_attr_t*, int*);
+    int pthread_attr_setinheritsched(pthread_attr_t*, int);
+    int pthread_attr_setschedpolicy(pthread_attr_t*, int);
+    int pthread_attr_setscope(in pthread_attr_t*, int);
+    int pthread_getschedparam(pthread_t, int*, sched_param*);
+    int pthread_setschedparam(pthread_t, int, sched_param*);
+    //int pthread_setschedprio(pthread_t, int);
+}
+
+//
+// Stack (TSA|TSS)
+//
+/*
+int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*); (TSA|TSS)
+int pthread_attr_getstackaddr(in pthread_attr_t*, void**); (TSA)
+int pthread_attr_getstacksize(in pthread_attr_t*, size_t*); (TSS)
+int pthread_attr_setstack(pthread_attr_t*, void*, size_t); (TSA|TSS)
+int pthread_attr_setstackaddr(pthread_attr_t*, void*); (TSA)
+int pthread_attr_setstacksize(pthread_attr_t*, size_t); (TSS)
+*/
+
+version( linux )
+{
+    int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
+    int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
+    int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+    int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
+    int pthread_attr_setstackaddr(pthread_attr_t*, void*);
+    int pthread_attr_setstacksize(pthread_attr_t*, size_t);
+}
+else version( OSX )
+{
+    int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
+    int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
+    int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+    int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
+    int pthread_attr_setstackaddr(pthread_attr_t*, void*);
+    int pthread_attr_setstacksize(pthread_attr_t*, size_t);
+}
+else version( freebsd )
+{
+    int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
+    int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
+    int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+    int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
+    int pthread_attr_setstackaddr(pthread_attr_t*, void*);
+    int pthread_attr_setstacksize(pthread_attr_t*, size_t);
+}
+
+//
+// Shared Synchronization (TSH)
+//
+/*
+int pthread_condattr_getpshared(in pthread_condattr_t*, int*);
+int pthread_condattr_setpshared(pthread_condattr_t*, int);
+int pthread_mutexattr_getpshared(in pthread_mutexattr_t*, int*);
+int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int);
+int pthread_rwlockattr_getpshared(in pthread_rwlockattr_t*, int*);
+int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int);
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/pwd.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,137 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.pwd;
+
+private import core.sys.posix.config;
+public import core.sys.posix.sys.types; // for gid_t, uid_t
+
+extern (C):
+
+//
+// Required
+//
+/*
+struct passwd
+{
+    char*   pw_name;
+    uid_t   pw_uid;
+    gid_t   pw_gid;
+    char*   pw_dir;
+    char*   pw_shell;
+}
+
+passwd* getpwnam(in char*);
+passwd* getpwuid(uid_t);
+*/
+
+version( linux )
+{
+    struct passwd
+    {
+        char*   pw_name;
+        char*   pw_passwd;
+        uid_t   pw_uid;
+        gid_t   pw_gid;
+        char*   pw_gecos;
+        char*   pw_dir;
+        char*   pw_shell;
+    }
+}
+else version( OSX )
+{
+    struct passwd
+    {
+        char*   pw_name;
+        char*   pw_passwd;
+        uid_t   pw_uid;
+        gid_t   pw_gid;
+        time_t  pw_change;
+        char*   pw_class;
+        char*   pw_gecos;
+        char*   pw_dir;
+        char*   pw_shell;
+        time_t  pw_expire;
+    }
+}
+else version( freebsd )
+{
+    struct passwd
+    {
+        char*   pw_name;        /* user name */
+        char*   pw_passwd;      /* encrypted password */
+        uid_t   pw_uid;         /* user uid */
+        gid_t   pw_gid;         /* user gid */
+        time_t  pw_change;      /* password change time */
+        char*   pw_class;       /* user access class */
+        char*   pw_gecos;       /* Honeywell login info */
+        char*   pw_dir;     /* home directory */
+        char*   pw_shell;       /* default shell */
+        time_t  pw_expire;      /* account expiration */
+        int pw_fields;      /* internal: fields filled in */
+    }
+}
+
+passwd* getpwnam(in char*);
+passwd* getpwuid(uid_t);
+
+//
+// Thread-Safe Functions (TSF)
+//
+/*
+int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
+*/
+
+version( linux )
+{
+    int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+    int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
+}
+else version( OSX )
+{
+    int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+    int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
+}
+else version( freebsd )
+{
+    int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+    int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
+}
+//
+// XOpen (XSI)
+//
+/*
+void    endpwent();
+passwd* getpwent();
+void    setpwent();
+*/
+
+version( linux )
+{
+    void    endpwent();
+    passwd* getpwent();
+    void    setpwent();
+}
+else version ( OSX )
+{
+    void    endpwent();
+    passwd* getpwent();
+    void    setpwent();
+}
+else version ( freebsd )
+{
+    void    endpwent();
+    passwd* getpwent();
+    void    setpwent();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/sched.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,137 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.sched;
+
+private import core.sys.posix.config;
+public import core.sys.posix.time;
+public import core.sys.posix.sys.types;
+
+extern (C):
+
+//
+// Required
+//
+/*
+struct sched_param
+{
+    int sched_priority (THR)
+    int sched_ss_low_priority (SS|TSP)
+    struct timespec sched_ss_repl_period (SS|TSP)
+    struct timespec sched_ss_init_budget (SS|TSP)
+    int sched_ss_max_repl (SS|TSP)
+}
+
+SCHED_FIFO
+SCHED_RR
+SCHED_SPORADIC (SS|TSP)
+SCHED_OTHER
+
+int sched_getparam(pid_t, sched_param*);
+int sched_getscheduler(pid_t);
+int sched_setparam(pid_t, in sched_param*);
+int sched_setscheduler(pid_t, int, in sched_param*);
+*/
+
+version( linux )
+{
+    struct sched_param
+    {
+        int sched_priority;
+    }
+
+    enum SCHED_OTHER    = 0;
+    enum SCHED_FIFO     = 1;
+    enum SCHED_RR       = 2;
+    //SCHED_SPORADIC (SS|TSP)
+}
+else version( OSX )
+{
+    enum SCHED_OTHER    = 1;
+    enum SCHED_FIFO     = 4;
+    enum SCHED_RR       = 2;
+    //SCHED_SPORADIC (SS|TSP)
+
+    private enum __SCHED_PARAM_SIZE__ = 4;
+
+    struct sched_param
+    {
+        int                             sched_priority;
+        byte[__PTHREAD_MUTEX_SIZE__]    __opaque;
+    }
+}
+else version( freebsd )
+{
+    struct sched_param
+    {
+        int sched_priority;
+    }
+
+    enum SCHED_FIFO     = 1;
+    enum SCHED_OTHER    = 2;
+    enum SCHED_RR       = 3;
+    //SCHED_SPORADIC (SS|TSP)
+}
+
+int sched_getparam(pid_t, sched_param*);
+int sched_getscheduler(pid_t);
+int sched_setparam(pid_t, in sched_param*);
+int sched_setscheduler(pid_t, int, in sched_param*);
+
+//
+// Thread (THR)
+//
+/*
+int sched_yield();
+*/
+
+version( linux )
+{
+    int sched_yield();
+}
+else version( OSX )
+{
+    int sched_yield();
+}
+else version( freebsd )
+{
+    int sched_yield();
+}
+
+//
+// Scheduling (TPS)
+//
+/*
+int sched_get_priority_max(int);
+int sched_get_priority_min(int);
+int sched_rr_get_interval(pid_t, timespec*);
+*/
+
+version( linux )
+{
+    int sched_get_priority_max(int);
+    int sched_get_priority_min(int);
+    int sched_rr_get_interval(pid_t, timespec*);
+}
+else version( OSX )
+{
+    int sched_get_priority_min(int);
+    int sched_get_priority_max(int);
+    //int sched_rr_get_interval(pid_t, timespec*); // FIXME: unavailable?
+}
+else version( freebsd )
+{
+    int sched_get_priority_min(int);
+    int sched_get_priority_max(int);
+    int sched_rr_get_interval(pid_t, timespec*);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/semaphore.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,102 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.semaphore;
+
+private import core.sys.posix.config;
+private import core.sys.posix.time;
+
+extern (C):
+
+//
+// Required
+//
+/*
+sem_t
+SEM_FAILED
+
+int sem_close(sem_t*);
+int sem_destroy(sem_t*);
+int sem_getvalue(sem_t*, int*);
+int sem_init(sem_t*, int, uint);
+sem_t* sem_open(in char*, int, ...);
+int sem_post(sem_t*);
+int sem_trywait(sem_t*);
+int sem_unlink(in char*);
+int sem_wait(sem_t*);
+*/
+
+version( linux )
+{
+    private alias int __atomic_lock_t;
+
+    private struct _pthread_fastlock
+    {
+      c_long            __status;
+      __atomic_lock_t   __spinlock;
+    }
+
+    struct sem_t
+    {
+      _pthread_fastlock __sem_lock;
+      int               __sem_value;
+      void*             __sem_waiting;
+    }
+
+    enum SEM_FAILED = cast(sem_t*) null;
+}
+else version( OSX )
+{
+    alias int sem_t;
+
+    enum SEM_FAILED = cast(sem_t*) null;
+}
+else version( freebsd )
+{
+    enum SEM_MAGIC  = 0x09fa4012;
+    enum SEM_USER   = 0;
+
+    alias void* sem_t;
+
+    enum SEM_FAILED = cast(sem_t*) null;
+}
+
+int sem_close(sem_t*);
+int sem_destroy(sem_t*);
+int sem_getvalue(sem_t*, int*);
+int sem_init(sem_t*, int, uint);
+sem_t* sem_open(in char*, int, ...);
+int sem_post(sem_t*);
+int sem_trywait(sem_t*);
+int sem_unlink(in char*);
+int sem_wait(sem_t*);
+
+//
+// Timeouts (TMO)
+//
+/*
+int sem_timedwait(sem_t*, in timespec*);
+*/
+
+version( linux )
+{
+    int sem_timedwait(sem_t*, in timespec*);
+}
+else version( OSX )
+{
+    int sem_timedwait(sem_t*, in timespec*);
+}
+else version( freebsd )
+{
+    int sem_timedwait(sem_t*, in timespec*);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/setjmp.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,108 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.setjmp;
+
+private import core.sys.posix.config;
+private import core.sys.posix.signal; // for sigset_t
+
+extern (C):
+
+//
+// Required
+//
+/*
+jmp_buf
+
+int  setjmp(jmp_buf);
+void longjmp(jmp_buf, int);
+*/
+
+version( linux )
+{
+    version( X86_64 )
+    {
+        //enum JB_BX      = 0;
+        //enum JB_BP      = 1;
+        //enum JB_12      = 2;
+        //enum JB_13      = 3;
+        //enum JB_14      = 4;
+        //enum JB_15      = 5;
+        //enum JB_SP      = 6;
+        //enum JB_PC      = 7;
+        //enum JB_SIZE    = 64;
+
+        alias long[8] __jmp_buf;
+    }
+    else version( X86 )
+    {
+        //enum JB_BX      = 0;
+        //enum JB_SI      = 1;
+        //enum JB_DI      = 2;
+        //enum JB_BP      = 3;
+        //enum JB_SP      = 4;
+        //enum JB_PC      = 5;
+        //enum JB_SIZE    = 24;
+
+        alias int[6] __jmp_buf;
+    }
+    else version ( SPARC )
+    {
+        alias int[3] __jmp_buf;
+    }
+
+    struct __jmp_buf_tag
+    {
+        __jmp_buf   __jmpbuf;
+        int         __mask_was_saved;
+        sigset_t    __saved_mask;
+    }
+
+    alias __jmp_buf_tag[1] jmp_buf;
+
+    alias _setjmp setjmp; // see XOpen block
+    void longjmp(jmp_buf, int);
+}
+
+//
+// C Extension (CX)
+//
+/*
+sigjmp_buf
+
+int  sigsetjmp(sigjmp_buf, int);
+void siglongjmp(sigjmp_buf, int);
+*/
+
+version( linux )
+{
+    alias jmp_buf sigjmp_buf;
+
+    int __sigsetjmp(sigjmp_buf, int);
+    alias __sigsetjmp sigsetjmp;
+    void siglongjmp(sigjmp_buf, int);
+}
+
+//
+// XOpen (XSI)
+//
+/*
+int  _setjmp(jmp_buf);
+void _longjmp(jmp_buf, int);
+*/
+
+version( linux )
+{
+    int  _setjmp(jmp_buf);
+    void _longjmp(jmp_buf, int);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/signal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,843 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.signal;
+
+private import core.sys.posix.config;
+public import core.stdc.signal;
+public import core.stdc.stddef;         // for size_t
+public import core.sys.posix.sys.types; // for pid_t
+//public import core.sys.posix.time;      // for timespec, now defined here
+
+extern (C):
+
+private alias void function(int) sigfn_t;
+private alias void function(int, siginfo_t*, void*) sigactfn_t;
+
+//
+// Required
+//
+/*
+SIG_DFL (defined in core.stdc.signal)
+SIG_ERR (defined in core.stdc.signal)
+SIG_IGN (defined in core.stdc.signal)
+
+sig_atomic_t (defined in core.stdc.signal)
+
+SIGEV_NONE
+SIGEV_SIGNAL
+SIGEV_THREAD
+
+union sigval
+{
+    int   sival_int;
+    void* sival_ptr;
+}
+
+SIGRTMIN
+SIGRTMAX
+
+SIGABRT (defined in core.stdc.signal)
+SIGALRM
+SIGBUS
+SIGCHLD
+SIGCONT
+SIGFPE (defined in core.stdc.signal)
+SIGHUP
+SIGILL (defined in core.stdc.signal)
+SIGINT (defined in core.stdc.signal)
+SIGKILL
+SIGPIPE
+SIGQUIT
+SIGSEGV (defined in core.stdc.signal)
+SIGSTOP
+SIGTERM (defined in core.stdc.signal)
+SIGTSTP
+SIGTTIN
+SIGTTOU
+SIGUSR1
+SIGUSR2
+SIGURG
+
+struct sigaction_t
+{
+    sigfn_t     sa_handler;
+    sigset_t    sa_mask;
+    sigactfn_t  sa_sigaction;
+}
+
+sigfn_t signal(int sig, sigfn_t func); (defined in core.stdc.signal)
+int raise(int sig);                    (defined in core.stdc.signal)
+*/
+
+//SIG_DFL (defined in core.stdc.signal)
+//SIG_ERR (defined in core.stdc.signal)
+//SIG_IGN (defined in core.stdc.signal)
+
+//sig_atomic_t (defined in core.stdc.signal)
+
+enum
+{
+  SIGEV_SIGNAL,
+  SIGEV_NONE,
+  SIGEV_THREAD
+}
+
+union sigval
+{
+    int     sival_int;
+    void*   sival_ptr;
+}
+
+private extern (C) int __libc_current_sigrtmin();
+private extern (C) int __libc_current_sigrtmax();
+
+alias __libc_current_sigrtmin SIGRTMIN;
+alias __libc_current_sigrtmax SIGRTMAX;
+
+version( linux )
+{
+    //SIGABRT (defined in core.stdc.signal)
+    enum SIGALRM    = 14;
+    enum SIGBUS     = 7;
+    enum SIGCHLD    = 17;
+    enum SIGCONT    = 18;
+    //SIGFPE (defined in core.stdc.signal)
+    enum SIGHUP     = 1;
+    //SIGILL (defined in core.stdc.signal)
+    //SIGINT (defined in core.stdc.signal)
+    enum SIGKILL    = 9;
+    enum SIGPIPE    = 13;
+    enum SIGQUIT    = 3;
+    //SIGSEGV (defined in core.stdc.signal)
+    enum SIGSTOP    = 19;
+    //SIGTERM (defined in core.stdc.signal)
+    enum SIGTSTP    = 20;
+    enum SIGTTIN    = 21;
+    enum SIGTTOU    = 22;
+    enum SIGUSR1    = 10;
+    enum SIGUSR2    = 12;
+    enum SIGURG     = 23;
+}
+else version( OSX )
+{
+    //SIGABRT (defined in core.stdc.signal)
+    enum SIGALRM    = 14;
+    enum SIGBUS     = 10;
+    enum SIGCHLD    = 20;
+    enum SIGCONT    = 19;
+    //SIGFPE (defined in core.stdc.signal)
+    enum SIGHUP     = 1;
+    //SIGILL (defined in core.stdc.signal)
+    //SIGINT (defined in core.stdc.signal)
+    enum SIGKILL    = 9;
+    enum SIGPIPE    = 13;
+    enum SIGQUIT    = 3;
+    //SIGSEGV (defined in core.stdc.signal)
+    enum SIGSTOP    = 17;
+    //SIGTERM (defined in core.stdc.signal)
+    enum SIGTSTP    = 18;
+    enum SIGTTIN    = 21;
+    enum SIGTTOU    = 22;
+    enum SIGUSR1    = 30;
+    enum SIGUSR2    = 31;
+    enum SIGURG     = 16;
+}
+else version( freebsd )
+{
+    //SIGABRT (defined in core.stdc.signal)
+    enum SIGALRM    = 14;
+    enum SIGBUS     = 10;
+    enum SIGCHLD    = 20;
+    enum SIGCONT    = 19;
+    //SIGFPE (defined in core.stdc.signal)
+    enum SIGHUP     = 1;
+    //SIGILL (defined in core.stdc.signal)
+    //SIGINT (defined in core.stdc.signal)
+    enum SIGKILL    = 9;
+    enum SIGPIPE    = 13;
+    enum SIGQUIT    = 3;
+    //SIGSEGV (defined in core.stdc.signal)
+    enum SIGSTOP    = 17;
+    //SIGTERM (defined in core.stdc.signal)
+    enum SIGTSTP    = 18;
+    enum SIGTTIN    = 21;
+    enum SIGTTOU    = 22;
+    enum SIGUSR1    = 30;
+    enum SIGUSR2    = 31;
+    enum SIGURG     = 16;
+}
+
+struct sigaction_t
+{
+    static if( true /* __USE_POSIX199309 */ )
+    {
+        union
+        {
+            sigfn_t     sa_handler;
+            sigactfn_t  sa_sigaction;
+        }
+    }
+    else
+    {
+        sigfn_t     sa_handler;
+    }
+    sigset_t        sa_mask;
+    int             sa_flags;
+
+    version( OSX ) {} else {
+    void function() sa_restorer;
+    }
+}
+
+//
+// C Extension (CX)
+//
+/*
+SIG_HOLD
+
+sigset_t
+pid_t   (defined in core.sys.types)
+
+SIGABRT (defined in core.stdc.signal)
+SIGFPE  (defined in core.stdc.signal)
+SIGILL  (defined in core.stdc.signal)
+SIGINT  (defined in core.stdc.signal)
+SIGSEGV (defined in core.stdc.signal)
+SIGTERM (defined in core.stdc.signal)
+
+SA_NOCLDSTOP (CX|XSI)
+SIG_BLOCK
+SIG_UNBLOCK
+SIG_SETMASK
+
+struct siginfo_t
+{
+    int     si_signo;
+    int     si_code;
+
+    version( XSI )
+    {
+        int     si_errno;
+        pid_t   si_pid;
+        uid_t   si_uid;
+        void*   si_addr;
+        int     si_status;
+        c_long  si_band;
+    }
+    version( RTS )
+    {
+        sigval  si_value;
+    }
+}
+
+SI_USER
+SI_QUEUE
+SI_TIMER
+SI_ASYNCIO
+SI_MESGQ
+
+int kill(pid_t, int);
+int sigaction(int, in sigaction_t*, sigaction_t*);
+int sigaddset(sigset_t*, int);
+int sigdelset(sigset_t*, int);
+int sigemptyset(sigset_t*);
+int sigfillset(sigset_t*);
+int sigismember(in sigset_t*, int);
+int sigpending(sigset_t*);
+int sigprocmask(int, in sigset_t*, sigset_t*);
+int sigsuspend(in sigset_t*);
+int sigwait(in sigset_t*, int*);
+*/
+
+version( linux )
+{
+    enum SIG_HOLD = cast(sigfn_t) 1;
+
+    private enum _SIGSET_NWORDS = 1024 / (8 * c_ulong.sizeof);
+
+    struct sigset_t
+    {
+        c_ulong[_SIGSET_NWORDS] __val;
+    }
+
+    // pid_t  (defined in core.sys.types)
+
+    //SIGABRT (defined in core.stdc.signal)
+    //SIGFPE  (defined in core.stdc.signal)
+    //SIGILL  (defined in core.stdc.signal)
+    //SIGINT  (defined in core.stdc.signal)
+    //SIGSEGV (defined in core.stdc.signal)
+    //SIGTERM (defined in core.stdc.signal)
+
+    enum SA_NOCLDSTOP   = 1; // (CX|XSI)
+
+    enum SIG_BLOCK      = 0;
+    enum SIG_UNBLOCK    = 1;
+    enum SIG_SETMASK    = 2;
+
+    private enum __SI_MAX_SIZE = 128;
+
+    static if( false /* __WORDSIZE == 64 */ )
+    {
+        private enum __SI_PAD_SIZE = ((__SI_MAX_SIZE / int.sizeof) - 4);
+    }
+    else
+    {
+        private enum __SI_PAD_SIZE = ((__SI_MAX_SIZE / int.sizeof) - 3);
+    }
+
+    struct siginfo_t
+    {
+        int si_signo;       // Signal number
+        int si_errno;       // If non-zero, an errno value associated with
+                            // this signal, as defined in <errno.h>
+        int si_code;        // Signal code
+
+        union _sifields_t
+        {
+            int _pad[__SI_PAD_SIZE];
+
+            // kill()
+            struct _kill_t
+            {
+                pid_t si_pid; // Sending process ID
+                uid_t si_uid; // Real user ID of sending process
+            } _kill_t _kill;
+
+            // POSIX.1b timers.
+            struct _timer_t
+            {
+                int    si_tid;     // Timer ID
+                int    si_overrun; // Overrun count
+                sigval si_sigval;  // Signal value
+            } _timer_t _timer;
+
+            // POSIX.1b signals
+            struct _rt_t
+            {
+                pid_t  si_pid;    // Sending process ID
+                uid_t  si_uid;    // Real user ID of sending process
+                sigval si_sigval; // Signal value
+            } _rt_t _rt;
+
+            // SIGCHLD
+            struct _sigchild_t
+            {
+                pid_t   si_pid;    // Which child
+                uid_t   si_uid;    // Real user ID of sending process
+                int     si_status; // Exit value or signal
+                clock_t si_utime;
+                clock_t si_stime;
+            } _sigchild_t _sigchld;
+
+            // SIGILL, SIGFPE, SIGSEGV, SIGBUS
+            struct _sigfault_t
+            {
+                void*     si_addr;  // Faulting insn/memory ref
+            } _sigfault_t _sigfault;
+
+            // SIGPOLL
+            struct _sigpoll_t
+            {
+                c_long   si_band;   // Band event for SIGPOLL
+                int      si_fd;
+            } _sigpoll_t _sigpoll;
+        } _sifields_t _sifields;
+    }
+
+    enum
+    {
+        SI_ASYNCNL = -60,
+        SI_TKILL   = -6,
+        SI_SIGIO,
+        SI_ASYNCIO,
+        SI_MESGQ,
+        SI_TIMER,
+        SI_QUEUE,
+        SI_USER,
+        SI_KERNEL  = 0x80
+    }
+
+    int kill(pid_t, int);
+    int sigaction(int, in sigaction_t*, sigaction_t*);
+    int sigaddset(sigset_t*, int);
+    int sigdelset(sigset_t*, int);
+    int sigemptyset(sigset_t*);
+    int sigfillset(sigset_t*);
+    int sigismember(in sigset_t*, int);
+    int sigpending(sigset_t*);
+    int sigprocmask(int, in sigset_t*, sigset_t*);
+    int sigsuspend(in sigset_t*);
+    int sigwait(in sigset_t*, int*);
+}
+else version( OSX )
+{
+    //SIG_HOLD
+
+    alias uint sigset_t;
+    // pid_t  (defined in core.sys.types)
+
+    //SIGABRT (defined in core.stdc.signal)
+    //SIGFPE  (defined in core.stdc.signal)
+    //SIGILL  (defined in core.stdc.signal)
+    //SIGINT  (defined in core.stdc.signal)
+    //SIGSEGV (defined in core.stdc.signal)
+    //SIGTERM (defined in core.stdc.signal)
+
+    //SA_NOCLDSTOP (CX|XSI)
+
+    //SIG_BLOCK
+    //SIG_UNBLOCK
+    //SIG_SETMASK
+
+    struct siginfo_t
+    {
+        int     si_signo;
+        int     si_errno;
+        int     si_code;
+        pid_t   si_pid;
+        uid_t   si_uid;
+        int     si_status;
+        void*   si_addr;
+        sigval  si_value;
+        int     si_band;
+        uint    pad[7];
+    }
+
+    //SI_USER
+    //SI_QUEUE
+    //SI_TIMER
+    //SI_ASYNCIO
+    //SI_MESGQ
+
+    int kill(pid_t, int);
+    int sigaction(int, in sigaction_t*, sigaction_t*);
+    int sigaddset(sigset_t*, int);
+    int sigdelset(sigset_t*, int);
+    int sigemptyset(sigset_t*);
+    int sigfillset(sigset_t*);
+    int sigismember(in sigset_t*, int);
+    int sigpending(sigset_t*);
+    int sigprocmask(int, in sigset_t*, sigset_t*);
+    int sigsuspend(in sigset_t*);
+    int sigwait(in sigset_t*, int*);
+}
+else version( freebsd )
+{
+    struct sigset_t
+    {
+        uint __bits[4];
+    }
+
+    struct siginfo_t
+    {
+        int si_signo;
+        int si_errno;
+        int si_code;
+        pid_t si_pid;
+        uid_t si_uid;
+        int si_status;
+        void* si_addr;
+        sigval si_value;
+        union __reason
+        {
+            struct __fault
+            {
+                int _trapno;
+            }
+            __fault _fault;
+            struct __timer
+            {
+                int _timerid;
+                int _overrun;
+            }
+            __timer _timer;
+            struct __mesgq
+            {
+                int _mqd;
+            }
+            __mesgq _mesgq;
+            struct __poll
+            {
+                c_long _band;
+            }
+            __poll _poll;
+            struct ___spare___
+            {
+                c_long __spare1__;
+                int[7] __spare2__;
+            }
+            ___spare___ __spare__;
+        }
+        __reason _reason;
+    }
+
+    int kill(pid_t, int);
+    int sigaction(int, in sigaction_t*, sigaction_t);
+    int sigaddset(sigset_t*, int);
+    int sigdelset(sigset_t*, int);
+    int sigemptyset(sigset_t *);
+    int sigfillset(sigset_t *);
+    int sigismember(in sigset_t *, int);
+    int sigpending(sigset_t *);
+    int sigprocmask(int, in sigset_t*, sigset_t*);
+    int sigsuspend(in sigset_t *);
+    int sigwait(in sigset_t*, int*);
+}
+
+
+//
+// XOpen (XSI)
+//
+/*
+SIGPOLL
+SIGPROF
+SIGSYS
+SIGTRAP
+SIGVTALRM
+SIGXCPU
+SIGXFSZ
+
+SA_ONSTACK
+SA_RESETHAND
+SA_RESTART
+SA_SIGINFO
+SA_NOCLDWAIT
+SA_NODEFER
+SS_ONSTACK
+SS_DISABLE
+MINSIGSTKSZ
+SIGSTKSZ
+
+ucontext_t // from ucontext
+mcontext_t // from ucontext
+
+struct stack_t
+{
+    void*   ss_sp;
+    size_t  ss_size;
+    int     ss_flags;
+}
+
+struct sigstack
+{
+    int   ss_onstack;
+    void* ss_sp;
+}
+
+ILL_ILLOPC
+ILL_ILLOPN
+ILL_ILLADR
+ILL_ILLTRP
+ILL_PRVOPC
+ILL_PRVREG
+ILL_COPROC
+ILL_BADSTK
+
+FPE_INTDIV
+FPE_INTOVF
+FPE_FLTDIV
+FPE_FLTOVF
+FPE_FLTUND
+FPE_FLTRES
+FPE_FLTINV
+FPE_FLTSUB
+
+SEGV_MAPERR
+SEGV_ACCERR
+
+BUS_ADRALN
+BUS_ADRERR
+BUS_OBJERR
+
+TRAP_BRKPT
+TRAP_TRACE
+
+CLD_EXITED
+CLD_KILLED
+CLD_DUMPED
+CLD_TRAPPED
+CLD_STOPPED
+CLD_CONTINUED
+
+POLL_IN
+POLL_OUT
+POLL_MSG
+POLL_ERR
+POLL_PRI
+POLL_HUP
+
+sigfn_t bsd_signal(int sig, sigfn_t func);
+sigfn_t sigset(int sig, sigfn_t func);
+
+int killpg(pid_t, int);
+int sigaltstack(in stack_t*, stack_t*);
+int sighold(int);
+int sigignore(int);
+int siginterrupt(int, int);
+int sigpause(int);
+int sigrelse(int);
+*/
+
+version( linux )
+{
+    enum SIGPOLL        = 29;
+    enum SIGPROF        = 27;
+    enum SIGSYS         = 31;
+    enum SIGTRAP        = 5;
+    enum SIGVTALRM      = 26;
+    enum SIGXCPU        = 24;
+    enum SIGXFSZ        = 25;
+
+    enum SA_ONSTACK     = 0x08000000;
+    enum SA_RESETHAND   = 0x80000000;
+    enum SA_RESTART     = 0x10000000;
+    enum SA_SIGINFO     = 4;
+    enum SA_NOCLDWAIT   = 2;
+    enum SA_NODEFER     = 0x40000000;
+    enum SS_ONSTACK     = 1;
+    enum SS_DISABLE     = 2;
+    enum MINSIGSTKSZ    = 2048;
+    enum SIGSTKSZ       = 8192;
+
+    //ucontext_t (defined in core.sys.posix.ucontext)
+    //mcontext_t (defined in core.sys.posix.ucontext)
+
+    struct stack_t
+    {
+        void*   ss_sp;
+        int     ss_flags;
+        size_t  ss_size;
+    }
+
+    struct sigstack
+    {
+        void*   ss_sp;
+        int     ss_onstack;
+    }
+
+    enum
+    {
+        ILL_ILLOPC = 1,
+        ILL_ILLOPN,
+        ILL_ILLADR,
+        ILL_ILLTRP,
+        ILL_PRVOPC,
+        ILL_PRVREG,
+        ILL_COPROC,
+        ILL_BADSTK
+    }
+
+    enum
+    {
+        FPE_INTDIV = 1,
+        FPE_INTOVF,
+        FPE_FLTDIV,
+        FPE_FLTOVF,
+        FPE_FLTUND,
+        FPE_FLTRES,
+        FPE_FLTINV,
+        FPE_FLTSUB
+    }
+
+    enum
+    {
+        SEGV_MAPERR = 1,
+        SEGV_ACCERR
+    }
+
+    enum
+    {
+        BUS_ADRALN = 1,
+        BUS_ADRERR,
+        BUS_OBJERR
+    }
+
+    enum
+    {
+        TRAP_BRKPT = 1,
+        TRAP_TRACE
+    }
+
+    enum
+    {
+        CLD_EXITED = 1,
+        CLD_KILLED,
+        CLD_DUMPED,
+        CLD_TRAPPED,
+        CLD_STOPPED,
+        CLD_CONTINUED
+    }
+
+    enum
+    {
+        POLL_IN = 1,
+        POLL_OUT,
+        POLL_MSG,
+        POLL_ERR,
+        POLL_PRI,
+        POLL_HUP
+    }
+
+    sigfn_t bsd_signal(int sig, sigfn_t func);
+    sigfn_t sigset(int sig, sigfn_t func);
+
+    int killpg(pid_t, int);
+    int sigaltstack(in stack_t*, stack_t*);
+    int sighold(int);
+    int sigignore(int);
+    int siginterrupt(int, int);
+    int sigpause(int);
+    int sigrelse(int);
+}
+
+//
+// Timer (TMR)
+//
+/*
+NOTE: This should actually be defined in core.sys.posix.time.
+      It is defined here instead to break a circular import.
+
+struct timespec
+{
+    time_t  tv_sec;
+    int     tv_nsec;
+}
+*/
+
+version( linux )
+{
+    struct timespec
+    {
+        time_t  tv_sec;
+        c_long  tv_nsec;
+    }
+}
+else version( OSX )
+{
+    struct timespec
+    {
+        time_t  tv_sec;
+        c_long  tv_nsec;
+    }
+}
+else version( freebsd )
+{
+    struct timespec
+    {
+        time_t  tv_sec;
+        c_long  tv_nsec;
+    }
+}
+
+//
+// Realtime Signals (RTS)
+//
+/*
+struct sigevent
+{
+    int             sigev_notify;
+    int             sigev_signo;
+    sigval          sigev_value;
+    void(*)(sigval) sigev_notify_function;
+    pthread_attr_t* sigev_notify_attributes;
+}
+
+int sigqueue(pid_t, int, in sigval);
+int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*);
+int sigwaitinfo(in sigset_t*, siginfo_t*);
+*/
+
+version( linux )
+{
+    private enum __SIGEV_MAX_SIZE = 64;
+
+    static if( false /* __WORDSIZE == 64 */ )
+    {
+        private enum __SIGEV_PAD_SIZE = ((__SIGEV_MAX_SIZE / int.sizeof) - 4);
+    }
+    else
+    {
+        private enum __SIGEV_PAD_SIZE = ((__SIGEV_MAX_SIZE / int.sizeof) - 3);
+    }
+
+    struct sigevent
+    {
+        sigval      sigev_value;
+        int         sigev_signo;
+        int         sigev_notify;
+
+        union _sigev_un_t
+        {
+            int[__SIGEV_PAD_SIZE] _pad;
+            pid_t                 _tid;
+
+            struct _sigev_thread_t
+            {
+                void function(sigval)   _function;
+                void*                   _attribute;
+            } _sigev_thread_t _sigev_thread;
+        } _sigev_un_t _sigev_un;
+    }
+
+    int sigqueue(pid_t, int, in sigval);
+    int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*);
+    int sigwaitinfo(in sigset_t*, siginfo_t*);
+}
+else version( freebsd )
+{
+    struct sigevent
+    {
+        int             sigev_notify;
+        int             sigev_signo;
+        sigval          sigev_value;
+        union  _sigev_un
+        {
+            lwpid_t _threadid;
+            struct _sigev_thread
+            {
+                void function(sigval) _function;
+                void* _attribute;
+            }
+            c_long[8] __spare__;
+        }
+    }
+
+    int sigqueue(pid_t, int, in sigval);
+    int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*);
+    int sigwaitinfo(in sigset_t*, siginfo_t*);
+}
+//
+// Threads (THR)
+//
+/*
+int pthread_kill(pthread_t, int);
+int pthread_sigmask(int, in sigset_t*, sigset_t*);
+*/
+
+version( linux )
+{
+    int pthread_kill(pthread_t, int);
+    int pthread_sigmask(int, in sigset_t*, sigset_t*);
+}
+else version( OSX )
+{
+    int pthread_kill(pthread_t, int);
+    int pthread_sigmask(int, in sigset_t*, sigset_t*);
+}
+else version( freebsd )
+{
+    int pthread_kill(pthread_t, int);
+    int pthread_sigmask(int, in sigset_t*, sigset_t*);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/stdio.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,219 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.stdio;
+
+private import core.sys.posix.config;
+public import core.stdc.stdio;
+public import core.sys.posix.sys.types; // for off_t
+
+extern (C):
+
+//
+// Required (defined in core.stdc.stdio)
+//
+/*
+BUFSIZ
+_IOFBF
+_IOLBF
+_IONBF
+L_tmpnam
+SEEK_CUR
+SEEK_END
+SEEK_SET
+FILENAME_MAX
+FOPEN_MAX
+TMP_MAX
+EOF
+NULL
+stderr
+stdin
+stdout
+FILE
+fpos_t
+size_t
+
+void   clearerr(FILE*);
+int    fclose(FILE*);
+int    feof(FILE*);
+int    ferror(FILE*);
+int    fflush(FILE*);
+int    fgetc(FILE*);
+int    fgetpos(FILE*, fpos_t *);
+char*  fgets(char*, int, FILE*);
+FILE*  fopen(in char*, in char*);
+int    fprintf(FILE*, in char*, ...);
+int    fputc(int, FILE*);
+int    fputs(in char*, FILE*);
+size_t fread(void *, size_t, size_t, FILE*);
+FILE*  freopen(in char*, in char*, FILE*);
+int    fscanf(FILE*, in char*, ...);
+int    fseek(FILE*, c_long, int);
+int    fsetpos(FILE*, in fpos_t*);
+c_long ftell(FILE*);
+size_t fwrite(in void *, size_t, size_t, FILE*);
+int    getc(FILE*);
+int    getchar();
+char*  gets(char*);
+void   perror(in char*);
+int    printf(in char*, ...);
+int    putc(int, FILE*);
+int    putchar(int);
+int    puts(in char*);
+int    remove(in char*);
+int    rename(in char*, in char*);
+void   rewind(FILE*);
+int    scanf(in char*, ...);
+void   setbuf(FILE*, char*);
+int    setvbuf(FILE*, char*, int, size_t);
+int    snprintf(char*, size_t, in char*, ...);
+int    sprintf(char*, in char*, ...);
+int    sscanf(in char*, in char*, int ...);
+FILE*  tmpfile();
+char*  tmpnam(char*);
+int    ungetc(int, FILE*);
+int    vfprintf(FILE*, in char*, va_list);
+int    vfscanf(FILE*, in char*, va_list);
+int    vprintf(in char*, va_list);
+int    vscanf(in char*, va_list);
+int    vsnprintf(char*, size_t, in char*, va_list);
+int    vsprintf(char*, in char*, va_list);
+int    vsscanf(in char*, in char*, va_list arg);
+*/
+
+version( linux )
+{
+    static if( __USE_LARGEFILE64 )
+    {
+        int   fgetpos64(FILE*, fpos_t *);
+        alias fgetpos64 fgetpos;
+
+        FILE* fopen64(in char*, in char*);
+        alias fopen64 fopen;
+
+        FILE* freopen64(in char*, in char*, FILE*);
+        alias freopen64 freopen;
+
+        int   fseek64(FILE*, c_long, int);
+        alias fseek64 fseek;
+
+        int   fsetpos64(FILE*, in fpos_t*);
+        alias fsetpos64 fsetpos;
+
+        FILE* tmpfile64();
+        alias tmpfile64 tmpfile;
+    }
+    else
+    {
+        int   fgetpos(FILE*, fpos_t *);
+        FILE* fopen(in char*, in char*);
+        FILE* freopen(in char*, in char*, FILE*);
+        int   fseek(FILE*, c_long, int);
+        int   fsetpos(FILE*, in fpos_t*);
+        FILE* tmpfile();
+    }
+}
+
+//
+// C Extension (CX)
+//
+/*
+L_ctermid
+
+char*  ctermid(char*);
+FILE*  fdopen(int, in char*);
+int    fileno(FILE*);
+int    fseeko(FILE*, off_t, int);
+off_t  ftello(FILE*);
+char*  gets(char*);
+FILE*  popen(in char*, in char*);
+*/
+
+version( linux )
+{
+    enum L_ctermid = 9;
+
+  static if( __USE_FILE_OFFSET64 )
+  {
+    int   fseeko64(FILE*, off_t, int);
+    alias fseeko64 fseeko;
+  }
+  else
+  {
+    int   fseeko(FILE*, off_t, int);
+  }
+
+  static if( __USE_LARGEFILE64 )
+  {
+    off_t ftello64(FILE*);
+    alias ftello64 ftello;
+  }
+  else
+  {
+    off_t ftello(FILE*);
+  }
+}
+else
+{
+    int   fseeko(FILE*, off_t, int);
+    off_t ftello(FILE*);
+}
+
+char*  ctermid(char*);
+FILE*  fdopen(int, in char*);
+int    fileno(FILE*);
+//int    fseeko(FILE*, off_t, int);
+//off_t  ftello(FILE*);
+char*  gets(char*);
+FILE*  popen(in char*, in char*);
+
+//
+// Thread-Safe Functions (TSF)
+//
+/*
+void   flockfile(FILE*);
+int    ftrylockfile(FILE*);
+void   funlockfile(FILE*);
+int    getc_unlocked(FILE*);
+int    getchar_unlocked();
+int    putc_unlocked(int, FILE*);
+int    putchar_unlocked(int);
+*/
+
+version( linux )
+{
+    void   flockfile(FILE*);
+    int    ftrylockfile(FILE*);
+    void   funlockfile(FILE*);
+    int    getc_unlocked(FILE*);
+    int    getchar_unlocked();
+    int    putc_unlocked(int, FILE*);
+    int    putchar_unlocked(int);
+}
+
+//
+// XOpen (XSI)
+//
+/*
+P_tmpdir
+va_list (defined in core.stdc.stdarg)
+
+char*  tempnam(in char*, in char*);
+*/
+
+version( linux )
+{
+    enum P_tmpdir  = "/tmp";
+
+    char*  tempnam(in char*, in char*);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/stdlib.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,310 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.stdlib;
+
+private import core.sys.posix.config;
+public import core.stdc.stdlib;
+public import core.sys.posix.sys.wait;
+
+extern (C):
+
+//
+// Required (defined in core.stdc.stdlib)
+//
+/*
+EXIT_FAILURE
+EXIT_SUCCESS
+NULL
+RAND_MAX
+MB_CUR_MAX
+div_t
+ldiv_t
+lldiv_t
+size_t
+wchar_t
+
+void    _Exit(int);
+void    abort();
+int     abs(int);
+int     atexit(void function());
+double  atof(in char*);
+int     atoi(in char*);
+c_long  atol(in char*);
+long    atoll(in char*);
+void*   bsearch(in void*, in void*, size_t, size_t, int function(in void*, in void*));
+void*   calloc(size_t, size_t);
+div_t   div(int, int);
+void    exit(int);
+void    free(void*);
+char*   getenv(in char*);
+c_long  labs(c_long);
+ldiv_t  ldiv(c_long, c_long);
+long    llabs(long);
+lldiv_t lldiv(long, long);
+void*   malloc(size_t);
+int     mblen(in char*, size_t);
+size_t  mbstowcs(wchar_t*, in char*, size_t);
+int     mbtowc(wchar_t*, in char*, size_t);
+void    qsort(void*, size_t, size_t, int function(in void*, in void*));
+int     rand();
+void*   realloc(void*, size_t);
+void    srand(uint);
+double  strtod(in char*, char**);
+float   strtof(in char*, char**);
+c_long  strtol(in char*, char**, int);
+real    strtold(in char*, char**);
+long    strtoll(in char*, char**, int);
+c_ulong strtoul(in char*, char**, int);
+ulong   strtoull(in char*, char**, int);
+int     system(in char*);
+size_t  wcstombs(char*, in wchar_t*, size_t);
+int     wctomb(char*, wchar_t);
+*/
+
+//
+// Advisory Information (ADV)
+//
+/*
+int posix_memalign(void**, size_t, size_t);
+*/
+
+version( linux )
+{
+    int posix_memalign(void**, size_t, size_t);
+}
+
+//
+// C Extension (CX)
+//
+/*
+int setenv(in char*, in char*, int);
+int unsetenv(in char*);
+*/
+
+version( linux )
+{
+    int setenv(in char*, in char*, int);
+    int unsetenv(in char*);
+
+    void* valloc(size_t); // LEGACY non-standard
+}
+else version( OSX )
+{
+    int setenv(in char*, in char*, int);
+    int unsetenv(in char*);
+
+    void* valloc(size_t); // LEGACY non-standard
+}
+else version( freebsd )
+{
+    int setenv(in char*, in char*, int);
+    int unsetenv(in char*);
+
+    void* valloc(size_t); // LEGACY non-standard
+}
+
+//
+// Thread-Safe Functions (TSF)
+//
+/*
+int rand_r(uint*);
+*/
+
+version( linux )
+{
+    int rand_r(uint*);
+}
+else version( OSX )
+{
+    int rand_r(uint*);
+}
+else version( freebsd )
+{
+    int rand_r(uint*);
+}
+
+//
+// XOpen (XSI)
+//
+/*
+WNOHANG     (defined in core.sys.posix.sys.wait)
+WUNTRACED   (defined in core.sys.posix.sys.wait)
+WEXITSTATUS (defined in core.sys.posix.sys.wait)
+WIFEXITED   (defined in core.sys.posix.sys.wait)
+WIFSIGNALED (defined in core.sys.posix.sys.wait)
+WIFSTOPPED  (defined in core.sys.posix.sys.wait)
+WSTOPSIG    (defined in core.sys.posix.sys.wait)
+WTERMSIG    (defined in core.sys.posix.sys.wait)
+
+c_long a64l(in char*);
+double drand48();
+char*  ecvt(double, int, int *, int *); // LEGACY
+double erand48(ushort[3]);
+char*  fcvt(double, int, int *, int *); // LEGACY
+char*  gcvt(double, int, char*); // LEGACY
+// per spec: int getsubopt(char** char* const*, char**);
+int    getsubopt(char**, in char**, char**);
+int    grantpt(int);
+char*  initstate(uint, char*, size_t);
+c_long jrand48(ushort[3]);
+char*  l64a(c_long);
+void   lcong48(ushort[7]);
+c_long lrand48();
+char*  mktemp(char*); // LEGACY
+int    mkstemp(char*);
+c_long mrand48();
+c_long nrand48(ushort[3]);
+int    posix_openpt(int);
+char*  ptsname(int);
+int    putenv(char*);
+c_long random();
+char*  realpath(in char*, char*);
+ushort seed48(ushort[3]);
+void   setkey(in char*);
+char*  setstate(in char*);
+void   srand48(c_long);
+void   srandom(uint);
+int    unlockpt(int);
+*/
+
+version( linux )
+{
+    //WNOHANG     (defined in core.sys.posix.sys.wait)
+    //WUNTRACED   (defined in core.sys.posix.sys.wait)
+    //WEXITSTATUS (defined in core.sys.posix.sys.wait)
+    //WIFEXITED   (defined in core.sys.posix.sys.wait)
+    //WIFSIGNALED (defined in core.sys.posix.sys.wait)
+    //WIFSTOPPED  (defined in core.sys.posix.sys.wait)
+    //WSTOPSIG    (defined in core.sys.posix.sys.wait)
+    //WTERMSIG    (defined in core.sys.posix.sys.wait)
+
+    c_long a64l(in char*);
+    double drand48();
+    char*  ecvt(double, int, int *, int *); // LEGACY
+    double erand48(ushort[3]);
+    char*  fcvt(double, int, int *, int *); // LEGACY
+    char*  gcvt(double, int, char*); // LEGACY
+    int    getsubopt(char**, in char**, char**);
+    int    grantpt(int);
+    char*  initstate(uint, char*, size_t);
+    c_long jrand48(ushort[3]);
+    char*  l64a(c_long);
+    void   lcong48(ushort[7]);
+    c_long lrand48();
+    char*  mktemp(char*); // LEGACY
+    //int    mkstemp(char*);
+    c_long mrand48();
+    c_long nrand48(ushort[3]);
+    int    posix_openpt(int);
+    char*  ptsname(int);
+    int    putenv(char*);
+    c_long random();
+    char*  realpath(in char*, char*);
+    ushort seed48(ushort[3]);
+    void   setkey(in char*);
+    char*  setstate(in char*);
+    void   srand48(c_long);
+    void   srandom(uint);
+    int    unlockpt(int);
+
+  static if( __USE_LARGEFILE64 )
+  {
+    int    mkstemp64(char*);
+    alias  mkstemp64 mkstemp;
+  }
+  else
+  {
+    int    mkstemp(char*);
+  }
+}
+else version( OSX )
+{
+    //WNOHANG     (defined in core.sys.posix.sys.wait)
+    //WUNTRACED   (defined in core.sys.posix.sys.wait)
+    //WEXITSTATUS (defined in core.sys.posix.sys.wait)
+    //WIFEXITED   (defined in core.sys.posix.sys.wait)
+    //WIFSIGNALED (defined in core.sys.posix.sys.wait)
+    //WIFSTOPPED  (defined in core.sys.posix.sys.wait)
+    //WSTOPSIG    (defined in core.sys.posix.sys.wait)
+    //WTERMSIG    (defined in core.sys.posix.sys.wait)
+
+    c_long a64l(in char*);
+    double drand48();
+    char*  ecvt(double, int, int *, int *); // LEGACY
+    double erand48(ushort[3]);
+    char*  fcvt(double, int, int *, int *); // LEGACY
+    char*  gcvt(double, int, char*); // LEGACY
+    int    getsubopt(char**, in char**, char**);
+    int    grantpt(int);
+    char*  initstate(uint, char*, size_t);
+    c_long jrand48(ushort[3]);
+    char*  l64a(c_long);
+    void   lcong48(ushort[7]);
+    c_long lrand48();
+    char*  mktemp(char*); // LEGACY
+    int    mkstemp(char*);
+    c_long mrand48();
+    c_long nrand48(ushort[3]);
+    int    posix_openpt(int);
+    char*  ptsname(int);
+    int    putenv(char*);
+    c_long random();
+    char*  realpath(in char*, char*);
+    ushort seed48(ushort[3]);
+    void   setkey(in char*);
+    char*  setstate(in char*);
+    void   srand48(c_long);
+    void   srandom(uint);
+    int    unlockpt(int);
+}
+else version( freebsd )
+{
+    //WNOHANG     (defined in core.sys.posix.sys.wait)
+    //WUNTRACED   (defined in core.sys.posix.sys.wait)
+    //WEXITSTATUS (defined in core.sys.posix.sys.wait)
+    //WIFEXITED   (defined in core.sys.posix.sys.wait)
+    //WIFSIGNALED (defined in core.sys.posix.sys.wait)
+    //WIFSTOPPED  (defined in core.sys.posix.sys.wait)
+    //WSTOPSIG    (defined in core.sys.posix.sys.wait)
+    //WTERMSIG    (defined in core.sys.posix.sys.wait)
+
+    c_long a64l(in char*);
+    double drand48();
+    //char*  ecvt(double, int, int *, int *); // LEGACY
+    double erand48(ushort[3]);
+    //char*  fcvt(double, int, int *, int *); // LEGACY
+    //char*  gcvt(double, int, char*); // LEGACY
+    int    getsubopt(char**, in char**, char**);
+    int    grantpt(int);
+    char*  initstate(uint, char*, size_t);
+    c_long jrand48(ushort[3]);
+    char*  l64a(c_long);
+    void   lcong48(ushort[7]);
+    c_long lrand48();
+    char*  mktemp(char*); // LEGACY
+    int    mkstemp(char*);
+    c_long mrand48();
+    c_long nrand48(ushort[3]);
+    int    posix_openpt(int);
+    char*  ptsname(int);
+    int    putenv(char*);
+    c_long random();
+    char*  realpath(in char*, char*);
+    ushort seed48(ushort[3]);
+    void   setkey(in char*);
+    char*  setstate(in char*);
+    void   srand48(c_long);
+    void   srandom(uint);
+    int    unlockpt(int);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/sys/ipc.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,104 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.sys.ipc;
+
+private import core.sys.posix.config;
+public import core.sys.posix.sys.types; // for uid_t, gid_t, mode_t, key_t
+
+extern (C):
+
+//
+// XOpen (XSI)
+//
+/*
+struct ipc_perm
+{
+    uid_t    uid;
+    gid_t    gid;
+    uid_t    cuid;
+    gid_t    cgid;
+    mode_t   mode;
+}
+
+IPC_CREAT
+IPC_EXCL
+IPC_NOWAIT
+
+IPC_PRIVATE
+
+IPC_RMID
+IPC_SET
+IPC_STAT
+
+key_t ftok(in char*, int);
+*/
+
+version( linux )
+{
+    struct ipc_perm
+    {
+        key_t   __key;
+        uid_t   uid;
+        gid_t   gid;
+        uid_t   cuid;
+        gid_t   cgid;
+        ushort  mode;
+        ushort  __pad1;
+        ushort  __seq;
+        ushort  __pad2;
+        c_ulong __unused1;
+        c_ulong __unused2;
+    }
+
+    enum IPC_CREAT      = 01000;
+    enum IPC_EXCL       = 02000;
+    enum IPC_NOWAIT     = 04000;
+
+    enum key_t IPC_PRIVATE = 0;
+
+    enum IPC_RMID       = 0;
+    enum IPC_SET        = 1;
+    enum IPC_STAT       = 2;
+
+    key_t ftok(in char*, int);
+}
+else version( OSX )
+{
+
+}
+else version( freebsd )
+{
+    struct ipc_perm
+    {
+        ushort cuid;
+        ushort cguid;
+        ushort uid;
+        ushort gid;
+        ushort mode;
+        ushort seq;
+        key_t key;
+    }
+
+    enum IPC_CREAT      = 01000;
+    enum IPC_EXCL       = 02000;
+    enum IPC_NOWAIT     = 04000;
+
+    enum key_t IPC_PRIVATE = 0;
+
+    enum IPC_RMID       = 0;
+    enum IPC_SET        = 1;
+    enum IPC_STAT       = 2;
+
+    key_t ftok(in char*, int);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/sys/mman.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,313 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.sys.mman;
+
+private import core.sys.posix.config;
+public import core.stdc.stddef;          // for size_t
+public import core.sys.posix.sys.types; // for off_t, mode_t
+
+extern (C):
+
+//
+// Advisory Information (ADV)
+//
+/*
+int posix_madvise(void*, size_t, int);
+*/
+
+//
+// Advisory Information and either Memory Mapped Files or Shared Memory Objects (MC1)
+//
+/*
+POSIX_MADV_NORMAL
+POSIX_MADV_SEQUENTIAL
+POSIX_MADV_RANDOM
+POSIX_MADV_WILLNEED
+POSIX_MADV_DONTNEED
+*/
+
+version( linux )
+{
+    enum POSIX_MADV_NORMAL      = 0;
+    enum POSIX_MADV_RANDOM      = 1;
+    enum POSIX_MADV_SEQUENTIAL  = 2;
+    enum POSIX_MADV_WILLNEED    = 3;
+    enum POSIX_MADV_DONTNEED    = 4;
+}
+else version( OSX )
+{
+    enum POSIX_MADV_NORMAL      = 0;
+    enum POSIX_MADV_RANDOM      = 1;
+    enum POSIX_MADV_SEQUENTIAL  = 2;
+    enum POSIX_MADV_WILLNEED    = 3;
+    enum POSIX_MADV_DONTNEED    = 4;
+}
+else version( freebsd )
+{
+    enum POSIX_MADV_NORMAL      = 0;
+    enum POSIX_MADV_RANDOM      = 1;
+    enum POSIX_MADV_SEQUENTIAL  = 2;
+    enum POSIX_MADV_WILLNEED    = 3;
+    enum POSIX_MADV_DONTNEED    = 4;
+}
+
+//
+// Memory Mapped Files, Shared Memory Objects, or Memory Protection (MC2)
+//
+/*
+PROT_READ
+PROT_WRITE
+PROT_EXEC
+PROT_NONE
+*/
+
+version( linux )
+{
+    enum PROT_NONE      = 0x0;
+    enum PROT_READ      = 0x1;
+    enum PROT_WRITE     = 0x2;
+    enum PROT_EXEC      = 0x4;
+}
+else version( OSX )
+{
+    enum PROT_NONE      = 0x00;
+    enum PROT_READ      = 0x01;
+    enum PROT_WRITE     = 0x02;
+    enum PROT_EXEC      = 0x04;
+}
+else version( freebsd )
+{
+    enum PROT_NONE      = 0x00;
+    enum PROT_READ      = 0x01;
+    enum PROT_WRITE     = 0x02;
+    enum PROT_EXEC      = 0x04;
+}
+
+//
+// Memory Mapped Files, Shared Memory Objects, or Typed Memory Objects (MC3)
+//
+/*
+void* mmap(void*, size_t, int, int, int, off_t);
+int munmap(void*, size_t);
+*/
+
+version( linux )
+{
+    //void* mmap(void*, size_t, int, int, int, off_t);
+    int   munmap(void*, size_t);
+
+  static if( __USE_LARGEFILE64 )
+  {
+    void* mmap64(void*, size_t, int, int, int, off_t);
+    alias mmap64 mmap;
+  }
+  else
+  {
+    void* mmap(void*, size_t, int, int, int, off_t);
+  }
+}
+else version( OSX )
+{
+    void* mmap(void*, size_t, int, int, int, off_t);
+    int   munmap(void*, size_t);
+}
+else version( freebsd )
+{
+    void* mmap(void*, size_t, int, int, int, off_t);
+    int   munmap(void*, size_t);
+}
+
+//
+// Memory Mapped Files (MF)
+//
+/*
+MAP_SHARED (MF|SHM)
+MAP_PRIVATE (MF|SHM)
+MAP_FIXED  (MF|SHM)
+MAP_FAILED (MF|SHM)
+
+MS_ASYNC (MF|SIO)
+MS_SYNC (MF|SIO)
+MS_INVALIDATE (MF|SIO)
+
+int msync(void*, size_t, int); (MF|SIO)
+*/
+
+version( linux )
+{
+    enum MAP_SHARED     = 0x01;
+    enum MAP_PRIVATE    = 0x02;
+    enum MAP_FIXED      = 0x10;
+    enum MAP_ANON       = 0x20; // non-standard
+
+    enum MAP_FAILED     = cast(void*) -1;
+
+    enum
+    {
+        MS_ASYNC         = 1,
+        MS_SYNC          = 4,
+        MS_INVALIDATE    = 2
+    }
+
+    int msync(void*, size_t, int);
+}
+else version( OSX )
+{
+    enum MAP_SHARED     = 0x0001;
+    enum MAP_PRIVATE    = 0x0002;
+    enum MAP_FIXED      = 0x0010;
+    enum MAP_ANON       = 0x1000; // non-standard
+
+    enum MAP_FAILED     = cast(void*)-1;
+
+    enum MS_ASYNC       = 0x0001;
+    enum MS_INVALIDATE  = 0x0002;
+    enum MS_SYNC        = 0x0010;
+
+    int msync(void*, size_t, int);
+}
+else version( freebsd )
+{
+    enum MAP_SHARED     = 0x0001;
+    enum MAP_PRIVATE    = 0x0002;
+    enum MAP_FIXED      = 0x0010;
+    enum MAP_ANON       = 0x1000; // non-standard
+
+    enum MAP_FAILED     = cast(void*)-1;
+
+    enum MS_SYNC        = 0x0000;
+    enum MS_ASYNC       = 0x0001;
+    enum MS_INVALIDATE  = 0x0002;
+
+    int msync(void*, size_t, int);
+}
+
+//
+// Process Memory Locking (ML)
+//
+/*
+MCL_CURRENT
+MCL_FUTURE
+
+int mlockall(int);
+int munlockall();
+*/
+
+version( linux )
+{
+    enum MCL_CURRENT    = 1;
+    enum MCL_FUTURE     = 2;
+
+    int mlockall(int);
+    int munlockall();
+
+}
+else version( OSX )
+{
+    enum MCL_CURRENT    = 0x0001;
+    enum MCL_FUTURE     = 0x0002;
+
+    int mlockall(int);
+    int munlockall();
+}
+else version( freebsd )
+{
+    enum MCL_CURRENT    = 0x0001;
+    enum MCL_FUTURE     = 0x0002;
+
+    int mlockall(int);
+    int munlockall();
+}
+
+//
+// Range Memory Locking (MLR)
+//
+/*
+int mlock(in void*, size_t);
+int munlock(in void*, size_t);
+*/
+
+version( linux )
+{
+    int mlock(in void*, size_t);
+    int munlock(in void*, size_t);
+}
+else version( OSX )
+{
+    int mlock(in void*, size_t);
+    int munlock(in void*, size_t);
+}
+else version( freebsd )
+{
+    int mlock(in void*, size_t);
+    int munlock(in void*, size_t);
+}
+
+//
+// Memory Protection (MPR)
+//
+/*
+int mprotect(void*, size_t, int);
+*/
+
+version( OSX )
+{
+    int mprotect(void*, size_t, int);
+}
+else version( freebsd )
+{
+    int mprotect(void*, size_t, int);
+}
+
+//
+// Shared Memory Objects (SHM)
+//
+/*
+int shm_open(in char*, int, mode_t);
+int shm_unlink(in char*);
+*/
+
+version( linux )
+{
+    int shm_open(in char*, int, mode_t);
+    int shm_unlink(in char*);
+}
+else version( OSX )
+{
+    int shm_open(in char*, int, mode_t);
+    int shm_unlink(in char*);
+}
+else version( freebsd )
+{
+    int shm_open(in char*, int, mode_t);
+    int shm_unlink(in char*);
+}
+
+//
+// Typed Memory Objects (TYM)
+//
+/*
+POSIX_TYPED_MEM_ALLOCATE
+POSIX_TYPED_MEM_ALLOCATE_CONTIG
+POSIX_TYPED_MEM_MAP_ALLOCATABLE
+
+struct posix_typed_mem_info
+{
+    size_t posix_tmi_length;
+}
+
+int posix_mem_offset(in void*, size_t, off_t *, size_t *, int *);
+int posix_typed_mem_get_info(int, struct posix_typed_mem_info *);
+int posix_typed_mem_open(in char*, int, int);
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/sys/select.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,180 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.sys.select;
+
+private import core.sys.posix.config;
+public import core.stdc.time;           // for timespec
+public import core.sys.posix.sys.time;  // for timeval
+public import core.sys.posix.sys.types; // for time_t
+public import core.sys.posix.signal;    // for sigset_t
+
+extern (C):
+
+//
+// Required
+//
+/*
+NOTE: This module requires timeval from core.sys.posix.sys.time, but timeval
+      is supposedly an XOpen extension.  As a result, this header will not
+      compile on platforms that are not XSI-compliant.  This must be resolved
+      on a per-platform basis.
+
+fd_set
+
+void FD_CLR(int fd, fd_set* fdset);
+int FD_ISSET(int fd, fd_set* fdset);
+void FD_SET(int fd, fd_set* fdset);
+void FD_ZERO(fd_set* fdset);
+
+FD_SETSIZE
+
+int  pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+int  select(int, fd_set*, fd_set*, fd_set*, timeval*);
+*/
+
+version( linux )
+{
+    private
+    {
+        alias c_long __fd_mask;
+        enum __NFDBITS = 8 * __fd_mask.sizeof;
+
+        extern (D) int __FDELT( int d )
+        {
+            return d / __NFDBITS;
+        }
+
+        extern (D) int __FDMASK( int d )
+        {
+            return cast(__fd_mask) 1 << ( d % __NFDBITS );
+        }
+    }
+
+    enum FD_SETSIZE = 1024;
+
+    struct fd_set
+    {
+        __fd_mask[FD_SETSIZE / __NFDBITS] fds_bits;
+    }
+
+    extern (D) void FD_CLR( int fd, fd_set* fdset )
+    {
+        fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
+    }
+
+    extern (D) int  FD_ISSET( int fd, fd_set* fdset )
+    {
+        return fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd );
+    }
+
+    extern (D) void FD_SET( int fd, fd_set* fdset )
+    {
+        fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
+    }
+
+    extern (D) void FD_ZERO( fd_set* fdset )
+    {
+        fdset.fds_bits[0 .. $] = 0;
+    }
+
+    /+
+     + GNU ASM Implementation
+     +
+    # define __FD_ZERO(fdsp)                                \
+      do {                                                  \
+        int __d0, __d1;                                     \
+        __asm__ __volatile__ ("cld; rep; stosl"             \
+                  : "=c" (__d0), "=D" (__d1)                \
+                  : "a" (0), "0" (sizeof (fd_set)           \
+                          / sizeof (__fd_mask)),            \
+                    "1" (&__FDS_BITS (fdsp)[0])             \
+                  : "memory");                              \
+      } while (0)
+
+    # define __FD_SET(fd, fdsp)                             \
+      __asm__ __volatile__ ("btsl %1,%0"                    \
+                : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)])    \
+                : "r" (((int) (fd)) % __NFDBITS)            \
+                : "cc","memory")
+    # define __FD_CLR(fd, fdsp)                             \
+      __asm__ __volatile__ ("btrl %1,%0"                    \
+                : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)])    \
+                : "r" (((int) (fd)) % __NFDBITS)            \
+                : "cc","memory")
+    # define __FD_ISSET(fd, fdsp)                           \
+      (__extension__                                        \
+       ({register char __result;                            \
+         __asm__ __volatile__ ("btl %1,%2 ; setcb %b0"      \
+                   : "=q" (__result)                        \
+                   : "r" (((int) (fd)) % __NFDBITS),        \
+                     "m" (__FDS_BITS (fdsp)[__FDELT (fd)])  \
+                   : "cc");                                 \
+         __result; }))
+     +/
+
+    int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+    int select(int, fd_set*, fd_set*, fd_set*, timeval*);
+}
+else version( OSX )
+{
+    private
+    {
+        enum uint __DARWIN_NBBY    = 8;                            /* bits in a byte */
+        enum uint __DARWIN_NFDBITS = (int.sizeof * __DARWIN_NBBY); /* bits per mask */
+    }
+
+    enum FD_SETSIZE = 1024;
+
+    struct fd_set
+    {
+        int[(FD_SETSIZE + (__DARWIN_NFDBITS - 1)) / __DARWIN_NFDBITS] fds_bits;
+    }
+
+    extern (D) void FD_CLR( int fd, fd_set* fdset )
+    {
+        fdset.fds_bits[fd / __DARWIN_NFDBITS] &= ~(1 << (fd % __DARWIN_NFDBITS));
+    }
+
+    extern (D) int  FD_ISSET( int fd, fd_set* fdset )
+    {
+        return fdset.fds_bits[fd / __DARWIN_NFDBITS] & (1 << (fd % __DARWIN_NFDBITS));
+    }
+
+    extern (D) void FD_SET( int fd, fd_set* fdset )
+    {
+        fdset.fds_bits[fd / __DARWIN_NFDBITS] |= 1 << (fd % __DARWIN_NFDBITS);
+    }
+
+    extern (D) void FD_ZERO( fd_set* fdset )
+    {
+        fdset.fds_bits[0 .. $] = 0;
+    }
+
+    int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+    int select(int, fd_set*, fd_set*, fd_set*, timeval*);
+}
+else version( freebsd )
+{
+    private
+    {
+        enum uint _NFDBITS   = c_ulong.sizeof * 8;
+    }
+
+    enum uint FD_SETSIZE = 1024;
+
+    struct fd_set
+    {
+        c_ulong fds_bits[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/sys/shm.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,116 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.sys.shm;
+
+private import core.sys.posix.config;
+public import core.sys.posix.sys.types; // for pid_t, time_t, key_t, size_t
+public import core.sys.posix.sys.ipc;
+
+extern (C):
+
+//
+// XOpen (XSI)
+//
+/*
+SHM_RDONLY
+SHM_RND
+
+SHMLBA
+
+shmatt_t
+
+struct shmid_ds
+{
+    ipc_perm    shm_perm;
+    size_t      shm_segsz;
+    pid_t       shm_lpid;
+    pid_t       shm_cpid;
+    shmatt_t    shm_nattch;
+    time_t      shm_atime;
+    time_t      shm_dtime;
+    time_t      shm_ctime;
+}
+
+void* shmat(int, in void*, int);
+int   shmctl(int, int, shmid_ds*);
+int   shmdt(in void*);
+int   shmget(key_t, size_t, int);
+*/
+
+version( linux )
+{
+    enum SHM_RDONLY     = 010000;
+    enum SHM_RND        = 020000;
+
+    int   __getpagesize();
+    alias __getpagesize SHMLBA;
+
+    alias c_ulong   shmatt_t;
+
+    struct shmid_ds
+    {
+        ipc_perm    shm_perm;
+        size_t      shm_segsz;
+        time_t      shm_atime;
+        c_ulong     __unused1;
+        time_t      shm_dtime;
+        c_ulong     __unused2;
+        time_t      shm_ctime;
+        c_ulong     __unused3;
+        pid_t       shm_cpid;
+        pid_t       shm_lpid;
+        shmatt_t    shm_nattch;
+        c_ulong     __unused4;
+        c_ulong     __unused5;
+    }
+
+    void* shmat(int, in void*, int);
+    int   shmctl(int, int, shmid_ds*);
+    int   shmdt(in void*);
+    int   shmget(key_t, size_t, int);
+}
+else version( freebsd )
+{
+    enum SHM_RDONLY     = 010000;
+    enum SHM_RND        = 020000;
+    enum SHMLBA         = 1 << 12; // PAGE_SIZE = (1<<PAGE_SHIFT)
+
+    alias c_ulong   shmatt_t;
+
+    struct shmid_ds
+    {
+        ipc_perm    shm_perm;
+        size_t      shm_segsz;
+        time_t      shm_atime;
+        c_ulong     __unused1;
+        time_t      shm_dtime;
+        c_ulong     __unused2;
+        time_t      shm_ctime;
+        c_ulong     __unused3;
+        pid_t       shm_cpid;
+        pid_t       shm_lpid;
+        shmatt_t    shm_nattch;
+        c_ulong     __unused4;
+        c_ulong     __unused5;
+    }
+
+    void* shmat(int, in void*, int);
+    int   shmctl(int, int, shmid_ds*);
+    int   shmdt(in void*);
+    int   shmget(key_t, size_t, int);
+}
+else version( OSX )
+{
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/sys/socket.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,647 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.sys.socket;
+
+private import core.sys.posix.config;
+public import core.sys.posix.sys.types; // for ssize_t, size_t
+public import core.sys.posix.sys.uio;   // for iovec
+
+extern (C):
+
+//
+// Required
+//
+/*
+socklen_t
+sa_family_t
+
+struct sockaddr
+{
+    sa_family_t sa_family;
+    char        sa_data[];
+}
+
+struct sockaddr_storage
+{
+    sa_family_t ss_family;
+}
+
+struct msghdr
+{
+    void*         msg_name;
+    socklen_t     msg_namelen;
+    struct iovec* msg_iov;
+    int           msg_iovlen;
+    void*         msg_control;
+    socklen_t     msg_controllen;
+    int           msg_flags;
+}
+
+struct iovec {} // from core.sys.posix.sys.uio
+
+struct cmsghdr
+{
+    socklen_t cmsg_len;
+    int       cmsg_level;
+    int       cmsg_type;
+}
+
+SCM_RIGHTS
+
+CMSG_DATA(cmsg)
+CMSG_NXTHDR(mhdr,cmsg)
+CMSG_FIRSTHDR(mhdr)
+
+struct linger
+{
+    int l_onoff;
+    int l_linger;
+}
+
+SOCK_DGRAM
+SOCK_SEQPACKET
+SOCK_STREAM
+
+SOL_SOCKET
+
+SO_ACCEPTCONN
+SO_BROADCAST
+SO_DEBUG
+SO_DONTROUTE
+SO_ERROR
+SO_KEEPALIVE
+SO_LINGER
+SO_OOBINLINE
+SO_RCVBUF
+SO_RCVLOWAT
+SO_RCVTIMEO
+SO_REUSEADDR
+SO_SNDBUF
+SO_SNDLOWAT
+SO_SNDTIMEO
+SO_TYPE
+
+SOMAXCONN
+
+MSG_CTRUNC
+MSG_DONTROUTE
+MSG_EOR
+MSG_OOB
+MSG_PEEK
+MSG_TRUNC
+MSG_WAITALL
+
+AF_INET
+AF_UNIX
+AF_UNSPEC
+
+SHUT_RD
+SHUT_RDWR
+SHUT_WR
+
+int     accept(int, sockaddr*, socklen_t*);
+int     bind(int, in sockaddr*, socklen_t);
+int     connect(int, in sockaddr*, socklen_t);
+int     getpeername(int, sockaddr*, socklen_t*);
+int     getsockname(int, sockaddr*, socklen_t*);
+int     getsockopt(int, int, int, void*, socklen_t*);
+int     listen(int, int);
+ssize_t recv(int, void*, size_t, int);
+ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
+ssize_t recvmsg(int, msghdr*, int);
+ssize_t send(int, in void*, size_t, int);
+ssize_t sendmsg(int, in msghdr*, int);
+ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
+int     setsockopt(int, int, int, in void*, socklen_t);
+int     shutdown(int, int);
+int     socket(int, int, int);
+int     sockatmark(int);
+int     socketpair(int, int, int, int[2]);
+*/
+
+version( linux )
+{
+    alias uint   socklen_t;
+    alias ushort sa_family_t;
+
+    struct sockaddr
+    {
+        sa_family_t sa_family;
+        byte[14]    sa_data;
+    }
+
+    private enum : size_t
+    {
+        _SS_SIZE    = 128,
+        _SS_PADSIZE = _SS_SIZE - (c_ulong.sizeof * 2)
+    }
+
+    struct sockaddr_storage
+    {
+        sa_family_t ss_family;
+        c_ulong     __ss_align;
+        byte[_SS_PADSIZE] __ss_padding;
+    }
+
+    struct msghdr
+    {
+        void*     msg_name;
+        socklen_t msg_namelen;
+        iovec*    msg_iov;
+        size_t    msg_iovlen;
+        void*     msg_control;
+        size_t    msg_controllen;
+        int       msg_flags;
+    }
+
+    struct cmsghdr
+    {
+        size_t cmsg_len;
+        int    cmsg_level;
+        int    cmsg_type;
+        static if( false /* (!is( __STRICT_ANSI__ ) && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L */ )
+        {
+            ubyte[1] __cmsg_data;
+        }
+    }
+
+    enum : uint
+    {
+        SCM_RIGHTS = 0x01
+    }
+
+    static if( false /* (!is( __STRICT_ANSI__ ) && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L */ )
+    {
+        extern (D) ubyte[1] CMSG_DATA( cmsghdr* cmsg ) { return cmsg.__cmsg_data; }
+    }
+    else
+    {
+        extern (D) ubyte*   CMSG_DATA( cmsghdr* cmsg ) { return cast(ubyte*)( cmsg + 1 ); }
+    }
+
+    private cmsghdr* __cmsg_nxthdr(msghdr*, cmsghdr*);
+    alias            __cmsg_nxthdr CMSG_NXTHDR;
+
+    extern (D) size_t CMSG_FIRSTHDR( msghdr* mhdr )
+    {
+        return cast(size_t)( mhdr.msg_controllen >= cmsghdr.sizeof
+                             ? cast(cmsghdr*) mhdr.msg_control
+                             : cast(cmsghdr*) null );
+    }
+
+    struct linger
+    {
+        int l_onoff;
+        int l_linger;
+    }
+
+    enum
+    {
+        SOCK_DGRAM      = 2,
+        SOCK_SEQPACKET  = 5,
+        SOCK_STREAM     = 1
+    }
+
+    enum
+    {
+        SOL_SOCKET      = 1
+    }
+
+    enum
+    {
+        SO_ACCEPTCONN   = 30,
+        SO_BROADCAST    = 6,
+        SO_DEBUG        = 1,
+        SO_DONTROUTE    = 5,
+        SO_ERROR        = 4,
+        SO_KEEPALIVE    = 9,
+        SO_LINGER       = 13,
+        SO_OOBINLINE    = 10,
+        SO_RCVBUF       = 8,
+        SO_RCVLOWAT     = 18,
+        SO_RCVTIMEO     = 20,
+        SO_REUSEADDR    = 2,
+        SO_SNDBUF       = 7,
+        SO_SNDLOWAT     = 19,
+        SO_SNDTIMEO     = 21,
+        SO_TYPE         = 3
+    }
+
+    enum
+    {
+        SOMAXCONN       = 128
+    }
+
+    enum : uint
+    {
+        MSG_CTRUNC      = 0x08,
+        MSG_DONTROUTE   = 0x04,
+        MSG_EOR         = 0x80,
+        MSG_OOB         = 0x01,
+        MSG_PEEK        = 0x02,
+        MSG_TRUNC       = 0x20,
+        MSG_WAITALL     = 0x100
+    }
+
+    enum
+    {
+        AF_INET         = 2,
+        AF_UNIX         = 1,
+        AF_UNSPEC       = 0
+    }
+
+    enum
+    {
+        SHUT_RD,
+        SHUT_WR,
+        SHUT_RDWR
+    }
+
+    int     accept(int, sockaddr*, socklen_t*);
+    int     bind(int, in sockaddr*, socklen_t);
+    int     connect(int, in sockaddr*, socklen_t);
+    int     getpeername(int, sockaddr*, socklen_t*);
+    int     getsockname(int, sockaddr*, socklen_t*);
+    int     getsockopt(int, int, int, void*, socklen_t*);
+    int     listen(int, int);
+    ssize_t recv(int, void*, size_t, int);
+    ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
+    ssize_t recvmsg(int, msghdr*, int);
+    ssize_t send(int, in void*, size_t, int);
+    ssize_t sendmsg(int, in msghdr*, int);
+    ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
+    int     setsockopt(int, int, int, in void*, socklen_t);
+    int     shutdown(int, int);
+    int     socket(int, int, int);
+    int     sockatmark(int);
+    int     socketpair(int, int, int, int[2]);
+}
+else version( OSX )
+{
+    alias uint   socklen_t;
+    alias ubyte  sa_family_t;
+
+    struct sockaddr
+    {
+        ubyte       sa_len;
+        sa_family_t sa_family;
+        byte[14]    sa_data;
+    }
+
+    private enum : size_t
+    {
+        _SS_PAD1    = long.sizeof - ubyte.sizeof - sa_family_t.sizeof,
+        _SS_PAD2    = 128 - ubyte.sizeof - sa_family_t.sizeof - _SS_PAD1 - long.sizeof
+    }
+
+    struct sockaddr_storage
+    {
+         ubyte          ss_len;
+         sa_family_t    ss_family;
+         byte[_SS_PAD1] __ss_pad1;
+         long           __ss_align;
+         byte[_SS_PAD2] __ss_pad2;
+    }
+
+    struct msghdr
+    {
+        void*     msg_name;
+        socklen_t msg_namelen;
+        iovec*    msg_iov;
+        int       msg_iovlen;
+        void*     msg_control;
+        socklen_t msg_controllen;
+        int       msg_flags;
+    }
+
+    struct cmsghdr
+    {
+         socklen_t cmsg_len;
+         int       cmsg_level;
+         int       cmsg_type;
+    }
+
+    enum : uint
+    {
+        SCM_RIGHTS = 0x01
+    }
+
+    /+
+    CMSG_DATA(cmsg)     ((unsigned char *)(cmsg) + \
+                         ALIGN(sizeof(struct cmsghdr)))
+    CMSG_NXTHDR(mhdr, cmsg) \
+                        (((unsigned char *)(cmsg) + ALIGN((cmsg)->cmsg_len) + \
+                         ALIGN(sizeof(struct cmsghdr)) > \
+                         (unsigned char *)(mhdr)->msg_control +(mhdr)->msg_controllen) ? \
+                         (struct cmsghdr *)0 /* NULL */ : \
+                         (struct cmsghdr *)((unsigned char *)(cmsg) + ALIGN((cmsg)->cmsg_len)))
+    CMSG_FIRSTHDR(mhdr) ((struct cmsghdr *)(mhdr)->msg_control)
+    +/
+
+    struct linger
+    {
+        int l_onoff;
+        int l_linger;
+    }
+
+    enum
+    {
+        SOCK_DGRAM      = 2,
+        SOCK_SEQPACKET  = 5,
+        SOCK_STREAM     = 1
+    }
+
+    enum : uint
+    {
+        SOL_SOCKET      = 0xffff
+    }
+
+    enum : uint
+    {
+        SO_ACCEPTCONN   = 0x0002,
+        SO_BROADCAST    = 0x0020,
+        SO_DEBUG        = 0x0001,
+        SO_DONTROUTE    = 0x0010,
+        SO_ERROR        = 0x1007,
+        SO_KEEPALIVE    = 0x0008,
+        SO_LINGER       = 0x1080,
+        SO_OOBINLINE    = 0x0100,
+        SO_RCVBUF       = 0x1002,
+        SO_RCVLOWAT     = 0x1004,
+        SO_RCVTIMEO     = 0x1006,
+        SO_REUSEADDR    = 0x0004,
+        SO_SNDBUF       = 0x1001,
+        SO_SNDLOWAT     = 0x1003,
+        SO_SNDTIMEO     = 0x1005,
+        SO_TYPE         = 0x1008
+    }
+
+    enum
+    {
+        SOMAXCONN       = 128
+    }
+
+    enum : uint
+    {
+        MSG_CTRUNC      = 0x20,
+        MSG_DONTROUTE   = 0x4,
+        MSG_EOR         = 0x8,
+        MSG_OOB         = 0x1,
+        MSG_PEEK        = 0x2,
+        MSG_TRUNC       = 0x10,
+        MSG_WAITALL     = 0x40
+    }
+
+    enum
+    {
+        AF_INET         = 2,
+        AF_UNIX         = 1,
+        AF_UNSPEC       = 0
+    }
+
+    enum
+    {
+        SHUT_RD,
+        SHUT_WR,
+        SHUT_RDWR
+    }
+
+    int     accept(int, sockaddr*, socklen_t*);
+    int     bind(int, in sockaddr*, socklen_t);
+    int     connect(int, in sockaddr*, socklen_t);
+    int     getpeername(int, sockaddr*, socklen_t*);
+    int     getsockname(int, sockaddr*, socklen_t*);
+    int     getsockopt(int, int, int, void*, socklen_t*);
+    int     listen(int, int);
+    ssize_t recv(int, void*, size_t, int);
+    ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
+    ssize_t recvmsg(int, msghdr*, int);
+    ssize_t send(int, in void*, size_t, int);
+    ssize_t sendmsg(int, in msghdr*, int);
+    ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
+    int     setsockopt(int, int, int, in void*, socklen_t);
+    int     shutdown(int, int);
+    int     socket(int, int, int);
+    int     sockatmark(int);
+    int     socketpair(int, int, int, int[2]);
+}
+else version( freebsd )
+{
+    alias uint   socklen_t;
+    alias ubyte  sa_family_t;
+
+    struct sockaddr
+    {
+        ubyte       sa_len;
+        sa_family_t sa_family;
+        byte[14]    sa_data;
+    }
+
+    private
+    {
+        enum _SS_ALIGNSIZE  = long.sizeof;
+        enum _SS_MAXSIZE    = 128;
+        enum _SS_PAD1SIZE   = _SS_ALIGNSIZE - ubyte.sizeof - sa_family_t.sizeof;
+        enum _SS_PAD2SIZE   = _SS_MAXSIZE - ubyte.sizeof - sa_family_t.sizeof - _SS_PAD1SIZE - _SS_ALIGNSIZE;
+    }
+
+    struct sockaddr_storage
+    {
+         ubyte              ss_len;
+         sa_family_t        ss_family;
+         byte[_SS_PAD1SIZE] __ss_pad1;
+         long               __ss_align;
+         byte[_SS_PAD2SIZE] __ss_pad2;
+    }
+
+    struct msghdr
+    {
+        void*     msg_name;
+        socklen_t msg_namelen;
+        iovec*    msg_iov;
+        int       msg_iovlen;
+        void*     msg_control;
+        socklen_t msg_controllen;
+        int       msg_flags;
+    }
+
+    struct cmsghdr
+    {
+         socklen_t cmsg_len;
+         int       cmsg_level;
+         int       cmsg_type;
+    }
+
+    enum : uint
+    {
+        SCM_RIGHTS = 0x01
+    }
+
+    /+
+    CMSG_DATA(cmsg)     ((unsigned char *)(cmsg) + \
+                         ALIGN(sizeof(struct cmsghdr)))
+    CMSG_NXTHDR(mhdr, cmsg) \
+                        (((unsigned char *)(cmsg) + ALIGN((cmsg)->cmsg_len) + \
+                         ALIGN(sizeof(struct cmsghdr)) > \
+                         (unsigned char *)(mhdr)->msg_control +(mhdr)->msg_controllen) ? \
+                         (struct cmsghdr *)0 /* NULL */ : \
+                         (struct cmsghdr *)((unsigned char *)(cmsg) + ALIGN((cmsg)->cmsg_len)))
+    CMSG_FIRSTHDR(mhdr) ((struct cmsghdr *)(mhdr)->msg_control)
+    +/
+
+    struct linger
+    {
+        int l_onoff;
+        int l_linger;
+    }
+
+    enum
+    {
+        SOCK_DGRAM      = 2,
+        SOCK_SEQPACKET  = 5,
+        SOCK_STREAM     = 1
+    }
+
+    enum : uint
+    {
+        SOL_SOCKET      = 0xffff
+    }
+
+    enum : uint
+    {
+        SO_ACCEPTCONN   = 0x0002,
+        SO_BROADCAST    = 0x0020,
+        SO_DEBUG        = 0x0001,
+        SO_DONTROUTE    = 0x0010,
+        SO_ERROR        = 0x1007,
+        SO_KEEPALIVE    = 0x0008,
+        SO_LINGER       = 0x1080,
+        SO_OOBINLINE    = 0x0100,
+        SO_RCVBUF       = 0x1002,
+        SO_RCVLOWAT     = 0x1004,
+        SO_RCVTIMEO     = 0x1006,
+        SO_REUSEADDR    = 0x0004,
+        SO_SNDBUF       = 0x1001,
+        SO_SNDLOWAT     = 0x1003,
+        SO_SNDTIMEO     = 0x1005,
+        SO_TYPE         = 0x1008
+    }
+
+    enum
+    {
+        SOMAXCONN       = 128
+    }
+
+    enum : uint
+    {
+        MSG_CTRUNC      = 0x20,
+        MSG_DONTROUTE   = 0x4,
+        MSG_EOR         = 0x8,
+        MSG_OOB         = 0x1,
+        MSG_PEEK        = 0x2,
+        MSG_TRUNC       = 0x10,
+        MSG_WAITALL     = 0x40
+    }
+
+    enum
+    {
+        AF_INET         = 2,
+        AF_UNIX         = 1,
+        AF_UNSPEC       = 0
+    }
+
+    enum
+    {
+        SHUT_RD = 0,
+        SHUT_WR = 1,
+        SHUT_RDWR = 2
+    }
+
+    int     accept(int, sockaddr*, socklen_t*);
+    int     bind(int, in sockaddr*, socklen_t);
+    int     connect(int, in sockaddr*, socklen_t);
+    int     getpeername(int, sockaddr*, socklen_t*);
+    int     getsockname(int, sockaddr*, socklen_t*);
+    int     getsockopt(int, int, int, void*, socklen_t*);
+    int     listen(int, int);
+    ssize_t recv(int, void*, size_t, int);
+    ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
+    ssize_t recvmsg(int, msghdr*, int);
+    ssize_t send(int, in void*, size_t, int);
+    ssize_t sendmsg(int, in msghdr*, int);
+    ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
+    int     setsockopt(int, int, int, in void*, socklen_t);
+    int     shutdown(int, int);
+    int     socket(int, int, int);
+    int     sockatmark(int);
+    int     socketpair(int, int, int, int[2]);
+}
+
+//
+// IPV6 (IP6)
+//
+/*
+AF_INET6
+*/
+
+version( linux )
+{
+    enum
+    {
+        AF_INET6    = 10
+    }
+}
+else version( OSX )
+{
+    enum
+    {
+        AF_INET6    = 30
+    }
+}
+else version( freebsd )
+{
+    enum
+    {
+        AF_INET6    = 28
+    }
+}
+
+//
+// Raw Sockets (RS)
+//
+/*
+SOCK_RAW
+*/
+
+version( linux )
+{
+    enum
+    {
+        SOCK_RAW    = 3
+    }
+}
+else version( OSX )
+{
+    enum
+    {
+        SOCK_RAW    = 3
+    }
+}
+else version( freebsd )
+{
+    enum
+    {
+        SOCK_RAW    = 3
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/sys/stat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,425 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.sys.stat;
+
+private import core.sys.posix.config;
+private import core.stdc.stdint;
+private import core.sys.posix.time;     // for timespec
+public import core.stdc.stddef;          // for size_t
+public import core.sys.posix.sys.types; // for off_t, mode_t
+
+extern (C):
+
+//
+// Required
+//
+/*
+struct stat
+{
+    dev_t   st_dev;
+    ino_t   st_ino;
+    mode_t  st_mode;
+    nlink_t st_nlink;
+    uid_t   st_uid;
+    gid_t   st_gid;
+    off_t   st_size;
+    time_t  st_atime;
+    time_t  st_mtime;
+    time_t  st_ctime;
+}
+
+S_IRWXU
+    S_IRUSR
+    S_IWUSR
+    S_IXUSR
+S_IRWXG
+    S_IRGRP
+    S_IWGRP
+    S_IXGRP
+S_IRWXO
+    S_IROTH
+    S_IWOTH
+    S_IXOTH
+S_ISUID
+S_ISGID
+S_ISVTX
+
+S_ISBLK(m)
+S_ISCHR(m)
+S_ISDIR(m)
+S_ISFIFO(m)
+S_ISREG(m)
+S_ISLNK(m)
+S_ISSOCK(m)
+
+S_TYPEISMQ(buf)
+S_TYPEISSEM(buf)
+S_TYPEISSHM(buf)
+
+int    chmod(in char*, mode_t);
+int    fchmod(int, mode_t);
+int    fstat(int, stat*);
+int    lstat(in char*, stat*);
+int    mkdir(in char*, mode_t);
+int    mkfifo(in char*, mode_t);
+int    stat(in char*, stat*);
+mode_t umask(mode_t);
+*/
+
+version( linux )
+{
+    static if( __USE_LARGEFILE64 )
+    {
+        private alias uint _pad_t;
+    }
+    else
+    {
+        private alias ushort _pad_t;
+    }
+
+    struct stat_t
+    {
+        dev_t       st_dev;
+        _pad_t      __pad1;
+      static if( __USE_FILE_OFFSET64 )
+      {
+        ino_t       __st_ino;
+      }
+      else
+      {
+        ino_t       st_ino;
+      }
+        mode_t      st_mode;
+        nlink_t     st_nlink;
+        uid_t       st_uid;
+        gid_t       st_gid;
+        dev_t       st_rdev;
+        _pad_t      __pad2;
+        off_t       st_size;
+        blksize_t   st_blksize;
+        blkcnt_t    st_blocks;
+      static if( false /*__USE_MISC*/ ) // true if _BSD_SOURCE || _SVID_SOURCE
+      {
+        timespec    st_atim;
+        timespec    st_mtim;
+        timespec    st_ctim;
+        alias st_atim.tv_sec st_atime;
+        alias st_mtim.tv_sec st_mtime;
+        alias st_ctim.tv_sec st_ctime;
+      }
+      else
+      {
+        time_t      st_atime;
+        c_ulong     st_atimensec;
+        time_t      st_mtime;
+        c_ulong     st_mtimensec;
+        time_t      st_ctime;
+        c_ulong     st_ctimensec;
+      }
+      static if( __USE_FILE_OFFSET64 )
+      {
+        ino_t       st_ino;
+      }
+      else
+      {
+        c_ulong     __unused4;
+        c_ulong     __unused5;
+      }
+    }
+
+    enum S_IRUSR    = 0400;
+    enum S_IWUSR    = 0200;
+    enum S_IXUSR    = 0100;
+    enum S_IRWXU    = S_IRUSR | S_IWUSR | S_IXUSR;
+
+    enum S_IRGRP    = S_IRUSR >> 3;
+    enum S_IWGRP    = S_IWUSR >> 3;
+    enum S_IXGRP    = S_IXUSR >> 3;
+    enum S_IRWXG    = S_IRWXU >> 3;
+
+    enum S_IROTH    = S_IRGRP >> 3;
+    enum S_IWOTH    = S_IWGRP >> 3;
+    enum S_IXOTH    = S_IXGRP >> 3;
+    enum S_IRWXO    = S_IRWXG >> 3;
+
+    enum S_ISUID    = 04000;
+    enum S_ISGID    = 02000;
+    enum S_ISVTX    = 01000;
+
+    private
+    {
+        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+        {
+            return ( mode & S_IFMT ) == mask;
+        }
+    }
+
+    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
+    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
+    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
+    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
+    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
+    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
+    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+
+    static if( true /*__USE_POSIX199309*/ )
+    {
+        extern bool S_TYPEISMQ( stat_t* buf )  { return false; }
+        extern bool S_TYPEISSEM( stat_t* buf ) { return false; }
+        extern bool S_TYPEISSHM( stat_t* buf ) { return false; }
+    }
+}
+else version( OSX )
+{
+    struct stat_t
+    {
+        dev_t       st_dev;
+        ino_t       st_ino;
+        mode_t      st_mode;
+        nlink_t     st_nlink;
+        uid_t       st_uid;
+        gid_t       st_gid;
+        dev_t       st_rdev;
+      static if( false /*!_POSIX_C_SOURCE || _DARWIN_C_SOURCE*/ )
+      {
+          timespec  st_atimespec;
+          timespec  st_mtimespec;
+          timespec  st_ctimespec;          
+      }
+      else
+      {
+        time_t      st_atime;
+        c_long      st_atimensec;
+        time_t      st_mtime;
+        c_long      st_mtimensec;
+        time_t      st_ctime;
+        c_long      st_ctimensec;
+      }
+        off_t       st_size;
+        blkcnt_t    st_blocks;
+        blksize_t   st_blksize;
+        uint        st_flags;
+        uint        st_gen;
+        int         st_lspare;
+        long        st_qspare[2];
+    }
+
+    enum S_IRUSR    = 0400;
+    enum S_IWUSR    = 0200;
+    enum S_IXUSR    = 0100;
+    enum S_IRWXU    = S_IRUSR | S_IWUSR | S_IXUSR;
+
+    enum S_IRGRP    = S_IRUSR >> 3;
+    enum S_IWGRP    = S_IWUSR >> 3;
+    enum S_IXGRP    = S_IXUSR >> 3;
+    enum S_IRWXG    = S_IRWXU >> 3;
+
+    enum S_IROTH    = S_IRGRP >> 3;
+    enum S_IWOTH    = S_IWGRP >> 3;
+    enum S_IXOTH    = S_IXGRP >> 3;
+    enum S_IRWXO    = S_IRWXG >> 3;
+
+    enum S_ISUID    = 04000;
+    enum S_ISGID    = 02000;
+    enum S_ISVTX    = 01000;
+
+    private
+    {
+        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+        {
+            return ( mode & S_IFMT ) == mask;
+        }
+    }
+
+    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
+    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
+    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
+    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
+    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
+    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
+    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+}
+else version( freebsd )
+{
+    struct stat_t
+    {
+        dev_t   st_dev;
+        ino_t   st_ino;
+        mode_t  st_mode;
+        nlink_t st_nlink;
+        uid_t   st_uid;
+        gid_t   st_gid;
+        dev_t   st_rdev;
+
+        timespec st_atimespec;
+        timespec st_mtimespec;
+        timespec st_ctimespec;
+        time_t st_atime()
+        {
+            return st_atimespec.tv_sec;
+        }
+        time_t st_mtime()
+        {
+            return st_mtimespec.tv_sec;
+        }
+        time_t st_ctime()
+        {
+            return st_ctimespec.tv_sec;
+        }
+
+        off_t       st_size;
+        blkcnt_t    st_blocks;
+        blksize_t   st_blksize;
+        fflags_t    st_flags;
+        uint        st_gen;
+        int         st_lspare;
+        timespec    st_birthtimespec;
+
+        byte[16 - timespec.sizeof] padding;
+    }
+
+    enum S_IRUSR    = 0000400;
+    enum S_IWUSR    = 0000200;
+    enum S_IXUSR    = 0000100;
+    enum S_IRWXU    = 0000700;
+
+    enum S_IRGRP    = 0000040;
+    enum S_IWGRP    = 0000020;
+    enum S_IXGRP    = 0000010;
+    enum S_IRWXG    = 0000070;
+
+    enum S_IROTH    = 0000004;
+    enum S_IWOTH    = 0000002;
+    enum S_IXOTH    = 0000001;
+    enum S_IRWXO    = 0000007;
+
+    enum S_ISUID    = 0004000;
+    enum S_ISGID    = 0002000;
+    enum S_ISVTX    = 0001000;
+
+    private
+    {
+        extern (D) bool S_ISTYPE( mode_t mode, uint mask )
+        {
+            return ( mode & S_IFMT ) == mask;
+        }
+    }
+
+    extern (D) bool S_ISBLK( mode_t mode )  { return S_ISTYPE( mode, S_IFBLK );  }
+    extern (D) bool S_ISCHR( mode_t mode )  { return S_ISTYPE( mode, S_IFCHR );  }
+    extern (D) bool S_ISDIR( mode_t mode )  { return S_ISTYPE( mode, S_IFDIR );  }
+    extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO );  }
+    extern (D) bool S_ISREG( mode_t mode )  { return S_ISTYPE( mode, S_IFREG );  }
+    extern (D) bool S_ISLNK( mode_t mode )  { return S_ISTYPE( mode, S_IFLNK );  }
+    extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); }
+}
+
+int    chmod(in char*, mode_t);
+int    fchmod(int, mode_t);
+//int    fstat(int, stat_t*);
+//int    lstat(in char*, stat_t*);
+int    mkdir(in char*, mode_t);
+int    mkfifo(in char*, mode_t);
+//int    stat(in char*, stat_t*);
+mode_t umask(mode_t);
+
+version( linux )
+{
+  static if( __USE_LARGEFILE64 )
+  {
+    int   fstat64(int, stat_t*);
+    alias fstat64 fstat;
+
+    int   lstat64(in char*, stat_t*);
+    alias lstat64 lstat;
+
+    int   stat64(in char*, stat_t*);
+    alias stat64 stat;
+  }
+  else
+  {
+    int   fstat(int, stat_t*);
+    int   lstat(in char*, stat_t*);
+    int   stat(in char*, stat_t*);
+  }
+}
+else
+{
+    int   fstat(int, stat_t*);
+    int   lstat(in char*, stat_t*);
+    int   stat(in char*, stat_t*);
+}
+
+//
+// Typed Memory Objects (TYM)
+//
+/*
+S_TYPEISTMO(buf)
+*/
+
+//
+// XOpen (XSI)
+//
+/*
+S_IFMT
+S_IFBLK
+S_IFCHR
+S_IFIFO
+S_IFREG
+S_IFDIR
+S_IFLNK
+S_IFSOCK
+
+int mknod(in 3char*, mode_t, dev_t);
+*/
+
+version( linux )
+{
+    enum S_IFMT     = 0170000;
+    enum S_IFBLK    = 0060000;
+    enum S_IFCHR    = 0020000;
+    enum S_IFIFO    = 0010000;
+    enum S_IFREG    = 0100000;
+    enum S_IFDIR    = 0040000;
+    enum S_IFLNK    = 0120000;
+    enum S_IFSOCK   = 0140000;
+
+    int mknod(in char*, mode_t, dev_t);
+}
+else version( OSX )
+{
+    enum S_IFMT     = 0170000;
+    enum S_IFBLK    = 0060000;
+    enum S_IFCHR    = 0020000;
+    enum S_IFIFO    = 0010000;
+    enum S_IFREG    = 0100000;
+    enum S_IFDIR    = 0040000;
+    enum S_IFLNK    = 0120000;
+    enum S_IFSOCK   = 0140000;
+
+    int mknod(in char*, mode_t, dev_t);
+}
+else version( freebsd )
+{
+    enum S_IFMT     = 0170000;
+    enum S_IFBLK    = 0060000;
+    enum S_IFCHR    = 0020000;
+    enum S_IFIFO    = 0010000;
+    enum S_IFREG    = 0100000;
+    enum S_IFDIR    = 0040000;
+    enum S_IFLNK    = 0120000;
+    enum S_IFSOCK   = 0140000;
+
+    int mknod(in char*, mode_t, dev_t);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/sys/time.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,123 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.sys.time;
+
+private import core.sys.posix.config;
+public import core.sys.posix.sys.types;  // for time_t, suseconds_t
+public import core.sys.posix.sys.select; // for fd_set, FD_CLR() FD_ISSET() FD_SET() FD_ZERO() FD_SETSIZE, select()
+
+extern (C):
+
+//
+// XOpen (XSI)
+//
+/*
+struct timeval
+{
+    time_t      tv_sec;
+    suseconds_t tv_usec;
+}
+
+struct itimerval
+{
+    timeval it_interval;
+    timeval it_value;
+}
+
+ITIMER_REAL
+ITIMER_VIRTUAL
+ITIMER_PROF
+
+int getitimer(int, itimerval*);
+int gettimeofday(timeval*, void*);
+int select(int, fd_set*, fd_set*, fd_set*, timeval*); (defined in core.sys.posix.sys.signal)
+int setitimer(int, in itimerval*, itimerval*);
+int utimes(in char*, in timeval[2]); // LEGACY
+*/
+
+version( linux )
+{
+    struct timeval
+    {
+        time_t      tv_sec;
+        suseconds_t tv_usec;
+    }
+
+    struct itimerval
+    {
+        timeval it_interval;
+        timeval it_value;
+    }
+
+    enum ITIMER_REAL    = 0;
+    enum ITIMER_VIRTUAL = 1;
+    enum ITIMER_PROF    = 2;
+
+    int getitimer(int, itimerval*);
+    int gettimeofday(timeval*, void*);
+    int setitimer(int, in itimerval*, itimerval*);
+    int utimes(in char*, in timeval[2]); // LEGACY
+}
+else version( OSX )
+{
+    struct timeval
+    {
+        time_t      tv_sec;
+        suseconds_t tv_usec;
+    }
+
+    struct itimerval
+    {
+        timeval it_interval;
+        timeval it_value;
+    }
+
+    // non-standard
+    struct timezone_t
+    {
+        int tz_minuteswest;
+        int tz_dsttime;
+    }
+
+    int getitimer(int, itimerval*);
+    int gettimeofday(timeval*, timezone_t*); // timezone_t* is normally void*
+    int setitimer(int, in itimerval*, itimerval*);
+    int utimes(in char*, in timeval[2]);
+}
+else version( freebsd )
+{
+    struct timeval
+    {
+        time_t      tv_sec;
+        suseconds_t tv_usec;
+    }
+
+    struct itimerval
+    {
+        timeval it_interval;
+        timeval it_value;
+    }
+
+    // non-standard
+    struct timezone_t
+    {
+        int tz_minuteswest;
+        int tz_dsttime;
+    }
+
+    int getitimer(int, itimerval*);
+    int gettimeofday(timeval*, timezone_t*); // timezone_t* is normally void*
+    int setitimer(int, in itimerval*, itimerval*);
+    int utimes(in char*, in timeval[2]);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/sys/types.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,429 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.sys.types;
+
+private import core.sys.posix.config;
+private import core.stdc.stdint;
+public import core.stdc.stddef; // for size_t
+public import core.stdc.time;   // for clock_t, time_t
+
+extern (C):
+
+//
+// Required
+//
+/*
+blkcnt_t
+blksize_t
+dev_t
+gid_t
+ino_t
+mode_t
+nlink_t
+off_t
+pid_t
+size_t
+ssize_t
+time_t
+uid_t
+*/
+
+version( linux )
+{
+  static if( __USE_FILE_OFFSET64 )
+  {
+    alias long      blkcnt_t;
+    alias ulong     ino_t;
+    alias long      off_t;
+  }
+  else
+  {
+    alias c_long    blkcnt_t;
+    alias c_ulong   ino_t;
+    alias c_long    off_t;
+  }
+    alias c_long    blksize_t;
+    alias ulong     dev_t;
+    alias uint      gid_t;
+    alias uint      mode_t;
+    alias c_ulong   nlink_t;
+    alias int       pid_t;
+    //size_t (defined in core.stdc.stddef)
+    alias c_long    ssize_t;
+    //time_t (defined in core.stdc.time)
+    alias uint      uid_t;
+}
+else version( OSX )
+{
+    alias long      blkcnt_t;
+    alias int       blksize_t;
+    alias int       dev_t;
+    alias uint      gid_t;
+    alias uint      ino_t;
+    alias ushort    mode_t;
+    alias ushort    nlink_t;
+    alias long      off_t;
+    alias int       pid_t;
+    //size_t (defined in core.stdc.stddef)
+    alias size_t    ssize_t;
+    //time_t (defined in core.stdc.time)
+    alias uint      uid_t;
+}
+else version( freebsd )
+{
+    alias long      blkcnt_t;
+    alias uint      blksize_t;
+    alias uint      dev_t;
+    alias uint      gid_t;
+    alias uint      ino_t;
+    alias ushort    mode_t;
+    alias ushort    nlink_t;
+    alias long      off_t;
+    alias int       pid_t;
+    //size_t (defined in core.stdc.stddef)
+    alias size_t    ssize_t;
+    //time_t (defined in core.stdc.time)
+    alias uint      uid_t;
+    alias uint      fflags_t;
+}
+
+//
+// XOpen (XSI)
+//
+/*
+clock_t
+fsblkcnt_t
+fsfilcnt_t
+id_t
+key_t
+suseconds_t
+useconds_t
+*/
+
+version( linux )
+{
+  static if( __USE_FILE_OFFSET64 )
+  {
+    alias ulong     fsblkcnt_t;
+    alias ulong     fsfilcnt_t;
+  }
+  else
+  {
+    alias c_ulong   fsblkcnt_t;
+    alias c_ulong   fsfilcnt_t;
+  }
+    // clock_t (defined in core.stdc.time)
+    alias uint      id_t;
+    alias int       key_t;
+    alias c_long    suseconds_t;
+    alias uint      useconds_t;
+}
+else version( OSX )
+{
+    //clock_t
+    alias uint  fsblkcnt_t;
+    alias uint  fsfilcnt_t;
+    alias uint  id_t;
+    // key_t
+    alias int   suseconds_t;
+    alias uint  useconds_t;
+}
+else version( freebsd )
+{
+    //clock_t
+    alias ulong     fsblkcnt_t;
+    alias ulong     fsfilcnt_t;
+    alias long      id_t;
+    alias c_long    key_t;
+    alias c_long    suseconds_t;
+    alias uint      useconds_t;
+}
+
+//
+// Thread (THR)
+//
+/*
+pthread_attr_t
+pthread_cond_t
+pthread_condattr_t
+pthread_key_t
+pthread_mutex_t
+pthread_mutexattr_t
+pthread_once_t
+pthread_rwlock_t
+pthread_rwlockattr_t
+pthread_t
+*/
+
+version( linux )
+{
+    private struct __sched_param
+    {
+        int __sched_priority;
+    }
+
+    struct pthread_attr_t
+    {
+        int             __detachstate;
+        int             __schedpolicy;
+        __sched_param   __schedparam;
+        int             __inheritsched;
+        int             __scope;
+        size_t          __guardsize;
+        int             __stackaddr_set;
+        void*           __stackaddr;
+        size_t          __stacksize;
+    }
+
+    private alias int __atomic_lock_t;
+
+    private struct _pthread_fastlock
+    {
+        c_long          __status;
+        __atomic_lock_t __spinlock;
+    }
+
+    private alias void* _pthread_descr;
+
+    private alias long __pthread_cond_align_t;
+
+    struct pthread_cond_t
+    {
+        _pthread_fastlock       __c_lock;
+        _pthread_descr          __c_waiting;
+        char[48 -
+             _pthread_fastlock.sizeof -
+             _pthread_descr.sizeof -
+             __pthread_cond_align_t.sizeof]
+                                __padding;
+        __pthread_cond_align_t  __align;
+    }
+
+    struct pthread_condattr_t
+    {
+        int __dummy;
+    }
+
+    alias uint pthread_key_t;
+
+    struct pthread_mutex_t
+    {
+        int                 __m_reserved;
+        int                 __m_count;
+        _pthread_descr      __m_owner;
+        int                 __m_kind;
+        _pthread_fastlock   __m_lock;
+    }
+
+    struct pthread_mutexattr_t
+    {
+        int __mutexkind;
+    }
+
+    alias int pthread_once_t;
+
+    struct pthread_rwlock_t
+    {
+        _pthread_fastlock   __rw_lock;
+        int                 __rw_readers;
+        _pthread_descr      __rw_writer;
+        _pthread_descr      __rw_read_waiting;
+        _pthread_descr      __rw_write_waiting;
+        int                 __rw_kind;
+        int                 __rw_pshared;
+    }
+
+    struct pthread_rwlockattr_t
+    {
+        int __lockkind;
+        int __pshared;
+    }
+
+    alias c_ulong pthread_t;
+}
+else version( OSX )
+{
+    version( X86_64 )
+    {
+        enum __PTHREAD_SIZE__               = 1168;
+        enum __PTHREAD_ATTR_SIZE__          = 56;
+        enum __PTHREAD_MUTEXATTR_SIZE__     = 8;
+        enum __PTHREAD_MUTEX_SIZE__         = 56;
+        enum __PTHREAD_CONDATTR_SIZE__      = 8;
+        enum __PTHREAD_COND_SIZE__          = 40;
+        enum __PTHREAD_ONCE_SIZE__          = 8;
+        enum __PTHREAD_RWLOCK_SIZE__        = 192;
+        enum __PTHREAD_RWLOCKATTR_SIZE__    = 16;
+    }
+    else version( X86 )
+    {
+        enum __PTHREAD_SIZE__               = 596;
+        enum __PTHREAD_ATTR_SIZE__          = 36;
+        enum __PTHREAD_MUTEXATTR_SIZE__     = 8;
+        enum __PTHREAD_MUTEX_SIZE__         = 40;
+        enum __PTHREAD_CONDATTR_SIZE__      = 4;
+        enum __PTHREAD_COND_SIZE__          = 24;
+        enum __PTHREAD_ONCE_SIZE__          = 4;
+        enum __PTHREAD_RWLOCK_SIZE__        = 124;
+        enum __PTHREAD_RWLOCKATTR_SIZE__    = 12;
+    }
+
+    struct pthread_handler_rec
+    {
+      void function(void*)  __routine;
+      void*                 __arg;
+      pthread_handler_rec*  __next;
+    }
+
+    struct pthread_attr_t
+    {
+        c_long                              __sig;
+        byte[__PTHREAD_ATTR_SIZE__]         __opaque;
+    }
+
+    struct pthread_cond_t
+    {
+        c_long                              __sig;
+        byte[__PTHREAD_COND_SIZE__]         __opaque;
+    }
+
+    struct pthread_condattr_t
+    {
+        c_long                              __sig;
+        byte[__PTHREAD_CONDATTR_SIZE__]     __opaque;
+    }
+
+    alias c_ulong pthread_key_t;
+
+    struct pthread_mutex_t
+    {
+        c_long                              __sig;
+        byte[__PTHREAD_MUTEX_SIZE__]        __opaque;
+    }
+
+    struct pthread_mutexattr_t
+    {
+        c_long                              __sig;
+        byte[__PTHREAD_MUTEXATTR_SIZE__]    __opaque;
+    }
+
+    struct pthread_once_t
+    {
+        c_long                              __sig;
+        byte[__PTHREAD_ONCE_SIZE__]         __opaque;
+    }
+
+    struct pthread_rwlock_t
+    {
+        c_long                              __sig;
+        byte[__PTHREAD_RWLOCK_SIZE__]       __opaque;
+    }
+
+    struct pthread_rwlockattr_t
+    {
+        c_long                              __sig;
+        byte[__PTHREAD_RWLOCKATTR_SIZE__]   __opaque;
+    }
+
+    private struct _opaque_pthread_t
+    {
+        c_long                  __sig;
+        pthread_handler_rec*    __cleanup_stack;
+        byte[__PTHREAD_SIZE__]  __opaque;
+    }
+
+    alias _opaque_pthread_t* pthread_t;
+}
+else version( freebsd )
+{
+    alias int lwpid_t;
+
+    alias void* pthread_attr_t;
+    alias void* pthread_cond_t;
+    alias void* pthread_condattr_t;
+    alias void* pthread_key_t;
+    alias void* pthread_mutex_t;
+    alias void* pthread_mutexattr_t;
+    alias void* pthread_once_t;
+    alias void* pthread_rwlock_t;
+    alias void* pthread_rwlockattr_t;
+    alias void* pthread_t;
+}
+
+//
+// Barrier (BAR)
+//
+/*
+pthread_barrier_t
+pthread_barrierattr_t
+*/
+
+version( linux )
+{
+    struct pthread_barrier_t
+    {
+        _pthread_fastlock   __ba_lock;
+        int                 __ba_required;
+        int                 __ba_present;
+        _pthread_descr      __ba_waiting;
+    }
+
+    struct pthread_barrierattr_t
+    {
+        int __pshared;
+    }
+}
+else version( freebsd )
+{
+    alias void* pthread_barrier_t;
+    alias void* pthread_barrierattr_t;
+}
+
+//
+// Spin (SPN)
+//
+/*
+pthread_spinlock_t
+*/
+
+version( linux )
+{
+    alias int pthread_spinlock_t; // volatile
+}
+else version( OSX )
+{
+    //struct pthread_spinlock_t;
+}
+else version( freebsd )
+{
+    alias void* pthread_spinlock_t;
+}
+
+//
+// Timer (TMR)
+//
+/*
+clockid_t
+timer_t
+*/
+
+//
+// Trace (TRC)
+//
+/*
+trace_attr_t
+trace_event_id_t
+trace_event_set_t
+trace_id_t
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/sys/uio.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,70 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.sys.uio;
+
+private import core.sys.posix.config;
+public import core.sys.posix.sys.types; // for ssize_t, size_t
+
+extern (C):
+
+//
+// Required
+//
+/*
+struct iovec
+{
+    void*  iov_base;
+    size_t iov_len;
+}
+
+ssize_t // from core.sys.posix.sys.types
+size_t  // from core.sys.posix.sys.types
+
+ssize_t readv(int, in iovec*, int);
+ssize_t writev(int, in iovec*, int);
+*/
+
+version( linux )
+{
+    struct iovec
+    {
+        void*  iov_base;
+        size_t iov_len;
+    }
+
+    ssize_t readv(int, in iovec*, int);
+    ssize_t writev(int, in iovec*, int);
+}
+else version( OSX )
+{
+    struct iovec
+    {
+        void*  iov_base;
+        size_t iov_len;
+    }
+
+    ssize_t readv(int, in iovec*, int);
+    ssize_t writev(int, in iovec*, int);
+}
+else version( freebsd )
+{
+    struct iovec
+    {
+        void*  iov_base;
+        size_t iov_len;
+    }
+
+    ssize_t readv(int, in iovec*, int);
+    ssize_t writev(int, in iovec*, int);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/sys/wait.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,141 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.sys.wait;
+
+private import core.sys.posix.config;
+public import core.sys.posix.sys.types; // for id_t, pid_t
+public import core.sys.posix.signal;    // for siginfo_t (XSI)
+//public import core.sys.posix.resource; // for rusage (XSI)
+
+extern (C):
+
+//
+// Required
+//
+/*
+WNOHANG
+WUNTRACED
+
+WEXITSTATUS
+WIFCONTINUED
+WIFEXITED
+WIFSIGNALED
+WIFSTOPPED
+WSTOPSIG
+WTERMSIG
+
+pid_t wait(int*);
+pid_t waitpid(pid_t, int*, int);
+*/
+
+version( linux )
+{
+    enum WNOHANG        = 1;
+    enum WUNTRACED      = 2;
+
+    private
+    {
+        enum __W_CONTINUED = 0xFFFF;
+
+        extern (D) int __WTERMSIG( int status ) { return status & 0x7F; }
+    }
+
+    //
+    // NOTE: These macros assume __USE_BSD is not defined in the relevant
+    //       C headers as the parameter definition there is different and
+    //       much more complicated.
+    //
+    extern (D) int  WEXITSTATUS( int status )  { return ( status & 0xFF00 ) >> 8;   }
+    extern (D) int  WIFCONTINUED( int status ) { return status == __W_CONTINUED;    }
+    extern (D) bool WIFEXITED( int status )    { return __WTERMSIG( status ) == 0;  }
+    extern (D) bool WIFSIGNALED( int status )
+    {
+        return ( cast(byte) ( ( status & 0x7F ) + 1 ) >> 1 ) > 0;
+    }
+    extern (D) bool WIFSTOPPED( int status )   { return ( status & 0xFF ) == 0x7F;  }
+    extern (D) int  WSTOPSIG( int status )     { return WEXITSTATUS( status );      }
+    extern (D) int  WTERMSIG( int status )     { return status & 0x7F;              }
+}
+else version( OSX )
+{
+    enum WNOHANG        = 1;
+    enum WUNTRACED      = 2;
+
+    private
+    {
+        enum _WSTOPPED = 0177;
+    }
+
+    extern (D) int _WSTATUS(int status)         { return (status & 0177);           }
+    extern (D) int  WEXITSTATUS( int status )   { return (status >> 8);             }
+    extern (D) int  WIFCONTINUED( int status )  { return status == 0x13;            }
+    extern (D) bool WIFEXITED( int status )     { return _WSTATUS(status) == 0;     }
+    extern (D) bool WIFSIGNALED( int status )
+    {
+        return _WSTATUS( status ) != _WSTOPPED && _WSTATUS( status ) != 0;
+    }
+    extern (D) bool WIFSTOPPED( int status )   { return _WSTATUS( status ) == _WSTOPPED; }
+    extern (D) int  WSTOPSIG( int status )     { return status >> 8;                     }
+    extern (D) int  WTERMSIG( int status )     { return _WSTATUS( status );              }
+}
+else version( freebsd )
+{
+    enum WNOHANG        = 1;
+    enum WUNTRACED      = 2;
+    enum WCONTINUED     = 4;
+
+    private
+    {
+        enum _WSTOPPED = 0177;
+    }
+
+    extern (D) int _WSTATUS(int status)         { return (status & 0177);           }
+    extern (D) int  WEXITSTATUS( int status )   { return (status >> 8);             }
+    extern (D) int  WIFCONTINUED( int status )  { return status == 0x13;            }
+    extern (D) bool WIFEXITED( int status )     { return _WSTATUS(status) == 0;     }
+    extern (D) bool WIFSIGNALED( int status )
+    {
+        return _WSTATUS( status ) != _WSTOPPED && _WSTATUS( status ) != 0;
+    }
+    extern (D) bool WIFSTOPPED( int status )   { return _WSTATUS( status ) == _WSTOPPED; }
+    extern (D) int  WSTOPSIG( int status )     { return status >> 8;                     }
+    extern (D) int  WTERMSIG( int status )     { return _WSTATUS( status );              }
+}
+else
+{
+    static assert( false );
+}
+
+pid_t wait(int*);
+pid_t waitpid(pid_t, int*, int);
+
+//
+// XOpen (XSI)
+//
+/*
+WEXITED
+WSTOPPED
+WCONTINUED
+WNOHANG
+WNOWAIT
+
+enum idtype_t
+{
+    P_ALL,
+    P_PID,
+    P_PGID
+}
+
+int waitid(idtype_t, id_t, siginfo_t*, int);
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/termios.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,528 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.termios;
+
+private import core.sys.posix.config;
+public import core.sys.posix.sys.types; // for pid_t
+
+extern (C):
+
+//
+// Required
+//
+/*
+cc_t
+speed_t
+tcflag_t
+
+NCCS
+
+struct termios
+{
+    tcflag_t   c_iflag;
+    tcflag_t   c_oflag;
+    tcflag_t   c_cflag;
+    tcflag_t   c_lflag;
+    cc_t[NCCS] c_cc;
+}
+
+VEOF
+VEOL
+VERASE
+VINTR
+VKILL
+VMIN
+VQUIT
+VSTART
+VSTOP
+VSUSP
+VTIME
+
+BRKINT
+ICRNL
+IGNBRK
+IGNCR
+IGNPAR
+INLCR
+INPCK
+ISTRIP
+IXOFF
+IXON
+PARMRK
+
+OPOST
+
+B0
+B50
+B75
+B110
+B134
+B150
+B200
+B300
+B600
+B1200
+B1800
+B2400
+B4800
+B9600
+B19200
+B38400
+
+CSIZE
+    CS5
+    CS6
+    CS7
+    CS8
+CSTOPB
+CREAD
+PARENB
+PARODD
+HUPCL
+CLOCAL
+
+ECHO
+ECHOE
+ECHOK
+ECHONL
+ICANON
+IEXTEN
+ISIG
+NOFLSH
+TOSTOP
+
+TCSANOW
+TCSADRAIN
+TCSAFLUSH
+
+TCIFLUSH
+TCIOFLUSH
+TCOFLUSH
+
+TCIOFF
+TCION
+TCOOFF
+TCOON
+
+speed_t cfgetispeed(in termios*);
+speed_t cfgetospeed(in termios*);
+int     cfsetispeed(termios*, speed_t);
+int     cfsetospeed(termios*, speed_t);
+int     tcdrain(int);
+int     tcflow(int, int);
+int     tcflush(int, int);
+int     tcgetattr(int, termios*);
+int     tcsendbreak(int, int);
+int     tcsetattr(int, int, in termios*);
+*/
+
+version( OSX )
+{
+    alias ubyte cc_t;
+    alias uint  speed_t;
+    alias uint  tcflag_t;
+
+    enum NCCS   = 20;
+
+    struct termios
+    {
+        tcflag_t   c_iflag;
+        tcflag_t   c_oflag;
+        tcflag_t   c_cflag;
+        tcflag_t   c_lflag;
+        cc_t[NCCS] c_cc;
+        speed_t    c_ispeed;
+        speed_t    c_ospeed;
+    }
+
+    enum VEOF       = 0;
+    enum VEOL       = 1;
+    enum VERASE     = 3;
+    enum VINTR      = 8;
+    enum VKILL      = 5;
+    enum VMIN       = 16;
+    enum VQUIT      = 9;
+    enum VSTART     = 12;
+    enum VSTOP      = 13;
+    enum VSUSP      = 10;
+    enum VTIME      = 17;
+
+    enum BRKINT     = 0x0000002;
+    enum ICRNL      = 0x0000100;
+    enum IGNBRK     = 0x0000001;
+    enum IGNCR      = 0x0000080;
+    enum IGNPAR     = 0x0000004;
+    enum INLCR      = 0x0000040;
+    enum INPCK      = 0x0000010;
+    enum ISTRIP     = 0x0000020;
+    enum IXOFF      = 0x0000400;
+    enum IXON       = 0x0000200;
+    enum PARMRK     = 0x0000008;
+
+    enum OPOST      = 0x0000001;
+
+    enum B0         = 0;
+    enum B50        = 50;
+    enum B75        = 75;
+    enum B110       = 110;
+    enum B134       = 134;
+    enum B150       = 150;
+    enum B200       = 200;
+    enum B300       = 300;
+    enum B600       = 600;
+    enum B1200      = 1200;
+    enum B1800      = 1800;
+    enum B2400      = 2400;
+    enum B4800      = 4800;
+    enum B9600      = 9600;
+    enum B19200     = 19200;
+    enum B38400     = 38400;
+
+    enum CSIZE      = 0x0000300;
+    enum   CS5      = 0x0000000;
+    enum   CS6      = 0x0000100;
+    enum   CS7      = 0x0000200;
+    enum   CS8      = 0x0000300;
+    enum CSTOPB     = 0x0000400;
+    enum CREAD      = 0x0000800;
+    enum PARENB     = 0x0001000;
+    enum PARODD     = 0x0002000;
+    enum HUPCL      = 0x0004000;
+    enum CLOCAL     = 0x0008000;
+
+    enum ECHO       = 0x00000008;
+    enum ECHOE      = 0x00000002;
+    enum ECHOK      = 0x00000004;
+    enum ECHONL     = 0x00000010;
+    enum ICANON     = 0x00000100;
+    enum IEXTEN     = 0x00000400;
+    enum ISIG       = 0x00000080;
+    enum NOFLSH     = 0x80000000;
+    enum TOSTOP     = 0x00400000;
+
+    enum TCSANOW    = 0;
+    enum TCSADRAIN  = 1;
+    enum TCSAFLUSH  = 2;
+
+    enum TCIFLUSH   = 1;
+    enum TCOFLUSH   = 2;
+    enum TCIOFLUSH  = 3;
+
+    enum TCIOFF     = 3;
+    enum TCION      = 4;
+    enum TCOOFF     = 1;
+    enum TCOON      = 2;
+
+    speed_t cfgetispeed(in termios*);
+    speed_t cfgetospeed(in termios*);
+    int     cfsetispeed(termios*, speed_t);
+    int     cfsetospeed(termios*, speed_t);
+    int     tcdrain(int);
+    int     tcflow(int, int);
+    int     tcflush(int, int);
+    int     tcgetattr(int, termios*);
+    int     tcsendbreak(int, int);
+    int     tcsetattr(int, int, in termios*);
+
+}
+else version( linux )
+{
+    alias ubyte cc_t;
+    alias uint  speed_t;
+    alias uint  tcflag_t;
+
+    enum NCCS   = 32;
+
+    struct termios
+    {
+        tcflag_t   c_iflag;
+        tcflag_t   c_oflag;
+        tcflag_t   c_cflag;
+        tcflag_t   c_lflag;
+        cc_t       c_line;
+        cc_t[NCCS] c_cc;
+        speed_t    c_ispeed;
+        speed_t    c_ospeed;
+    }
+
+    enum VEOF       = 4;
+    enum VEOL       = 11;
+    enum VERASE     = 2;
+    enum VINTR      = 0;
+    enum VKILL      = 3;
+    enum VMIN       = 6;
+    enum VQUIT      = 1;
+    enum VSTART     = 8;
+    enum VSTOP      = 9;
+    enum VSUSP      = 10;
+    enum VTIME      = 5;
+
+    enum BRKINT     = 0000002;
+    enum ICRNL      = 0000400;
+    enum IGNBRK     = 0000001;
+    enum IGNCR      = 0000200;
+    enum IGNPAR     = 0000004;
+    enum INLCR      = 0000100;
+    enum INPCK      = 0000020;
+    enum ISTRIP     = 0000040;
+    enum IXOFF      = 0010000;
+    enum IXON       = 0002000;
+    enum PARMRK     = 0000010;
+
+    enum OPOST      = 0000001;
+
+    enum B0         = 0000000;
+    enum B50        = 0000001;
+    enum B75        = 0000002;
+    enum B110       = 0000003;
+    enum B134       = 0000004;
+    enum B150       = 0000005;
+    enum B200       = 0000006;
+    enum B300       = 0000007;
+    enum B600       = 0000010;
+    enum B1200      = 0000011;
+    enum B1800      = 0000012;
+    enum B2400      = 0000013;
+    enum B4800      = 0000014;
+    enum B9600      = 0000015;
+    enum B19200     = 0000016;
+    enum B38400     = 0000017;
+
+    enum CSIZE      = 0000060;
+    enum   CS5      = 0000000;
+    enum   CS6      = 0000020;
+    enum   CS7      = 0000040;
+    enum   CS8      = 0000060;
+    enum CSTOPB     = 0000100;
+    enum CREAD      = 0000200;
+    enum PARENB     = 0000400;
+    enum PARODD     = 0001000;
+    enum HUPCL      = 0002000;
+    enum CLOCAL     = 0004000;
+
+    enum ECHO       = 0000010;
+    enum ECHOE      = 0000020;
+    enum ECHOK      = 0000040;
+    enum ECHONL     = 0000100;
+    enum ICANON     = 0000002;
+    enum IEXTEN     = 0100000;
+    enum ISIG       = 0000001;
+    enum NOFLSH     = 0000200;
+    enum TOSTOP     = 0000400;
+
+    enum TCSANOW    = 0;
+    enum TCSADRAIN  = 1;
+    enum TCSAFLUSH  = 2;
+
+    enum TCIFLUSH   = 0;
+    enum TCOFLUSH   = 1;
+    enum TCIOFLUSH  = 2;
+
+    enum TCIOFF     = 2;
+    enum TCION      = 3;
+    enum TCOOFF     = 0;
+    enum TCOON      = 1;
+
+    speed_t cfgetispeed(in termios*);
+    speed_t cfgetospeed(in termios*);
+    int     cfsetispeed(termios*, speed_t);
+    int     cfsetospeed(termios*, speed_t);
+    int     tcdrain(int);
+    int     tcflow(int, int);
+    int     tcflush(int, int);
+    int     tcgetattr(int, termios*);
+    int     tcsendbreak(int, int);
+    int     tcsetattr(int, int, in termios*);
+}
+else version ( freebsd )
+{
+    alias ubyte cc_t;
+    alias uint  speed_t;
+    alias uint  tcflag_t;
+
+    enum NCCS   = 20;
+
+    struct termios
+    {
+        tcflag_t   c_iflag;
+        tcflag_t   c_oflag;
+        tcflag_t   c_cflag;
+        tcflag_t   c_lflag;
+        cc_t[NCCS] c_cc;
+        speed_t    c_ispeed;
+        speed_t    c_ospeed;
+    }
+
+    enum VEOF       = 0;
+    enum VEOL       = 1;
+    enum VERASE     = 3;
+    enum VINTR      = 8;
+    enum VKILL      = 5;
+    enum VMIN       = 16;
+    enum VQUIT      = 9;
+    enum VSTART     = 12;
+    enum VSTOP      = 13;
+    enum VSUSP      = 10;
+    enum VTIME      = 17;
+
+    enum BRKINT     = 0x0000002;
+    enum ICRNL      = 0x0000100;
+    enum IGNBRK     = 0x0000001;
+    enum IGNCR      = 0x0000080;
+    enum IGNPAR     = 0x0000004;
+    enum INLCR      = 0x0000040;
+    enum INPCK      = 0x0000010;
+    enum ISTRIP     = 0x0000020;
+    enum IXOFF      = 0x0000400;
+    enum IXON       = 0x0000200;
+    enum PARMRK     = 0x0000008;
+
+    enum OPOST      = 0x0000001;
+
+    enum B0         = 0;
+    enum B50        = 50;
+    enum B75        = 75;
+    enum B110       = 110;
+    enum B134       = 134;
+    enum B150       = 150;
+    enum B200       = 200;
+    enum B300       = 300;
+    enum B600       = 600;
+    enum B1200      = 1200;
+    enum B1800      = 1800;
+    enum B2400      = 2400;
+    enum B4800      = 4800;
+    enum B9600      = 9600;
+    enum B19200     = 19200;
+    enum B38400     = 38400;
+
+    enum CSIZE      = 0x0000300;
+    enum   CS5      = 0x0000000;
+    enum   CS6      = 0x0000100;
+    enum   CS7      = 0x0000200;
+    enum   CS8      = 0x0000300;
+    enum CSTOPB     = 0x0000400;
+    enum CREAD      = 0x0000800;
+    enum PARENB     = 0x0001000;
+    enum PARODD     = 0x0002000;
+    enum HUPCL      = 0x0004000;
+    enum CLOCAL     = 0x0008000;
+
+    enum ECHO       = 0x00000008;
+    enum ECHOE      = 0x00000002;
+    enum ECHOK      = 0x00000004;
+    enum ECHONL     = 0x00000010;
+    enum ICANON     = 0x00000100;
+    enum IEXTEN     = 0x00000400;
+    enum ISIG       = 0x00000080;
+    enum NOFLSH     = 0x80000000;
+    enum TOSTOP     = 0x00400000;
+
+    enum TCSANOW    = 0;
+    enum TCSADRAIN  = 1;
+    enum TCSAFLUSH  = 2;
+
+    enum TCIFLUSH   = 1;
+    enum TCOFLUSH   = 2;
+    enum TCIOFLUSH  = 3;
+
+    enum TCIOFF     = 3;
+    enum TCION      = 4;
+    enum TCOOFF     = 1;
+    enum TCOON      = 2;
+
+    speed_t cfgetispeed(in termios*);
+    speed_t cfgetospeed(in termios*);
+    int     cfsetispeed(termios*, speed_t);
+    int     cfsetospeed(termios*, speed_t);
+    int     tcdrain(int);
+    int     tcflow(int, int);
+    int     tcflush(int, int);
+    int     tcgetattr(int, termios*);
+    int     tcsendbreak(int, int);
+    int     tcsetattr(int, int, in termios*);
+
+}
+
+//
+// XOpen (XSI)
+//
+/*
+IXANY
+
+ONLCR
+OCRNL
+ONOCR
+ONLRET
+OFILL
+NLDLY
+    NL0
+    NL1
+CRDLY
+    CR0
+    CR1
+    CR2
+    CR3
+TABDLY
+    TAB0
+    TAB1
+    TAB2
+    TAB3
+BSDLY
+    BS0
+    BS1
+VTDLY
+    VT0
+    VT1
+FFDLY
+    FF0
+    FF1
+
+pid_t   tcgetsid(int);
+*/
+
+version( linux )
+{
+    enum IXANY      = 0004000;
+
+    enum ONLCR      = 0000004;
+    enum OCRNL      = 0000010;
+    enum ONOCR      = 0000020;
+    enum ONLRET     = 0000040;
+    enum OFILL      = 0000100;
+    enum NLDLY      = 0000400;
+    enum   NL0      = 0000000;
+    enum   NL1      = 0000400;
+    enum CRDLY      = 0003000;
+    enum   CR0      = 0000000;
+    enum   CR1      = 0001000;
+    enum   CR2      = 0002000;
+    enum   CR3      = 0003000;
+    enum TABDLY     = 0014000;
+    enum   TAB0     = 0000000;
+    enum   TAB1     = 0004000;
+    enum   TAB2     = 0010000;
+    enum   TAB3     = 0014000;
+    enum BSDLY      = 0020000;
+    enum   BS0      = 0000000;
+    enum   BS1      = 0020000;
+    enum VTDLY      = 0040000;
+    enum   VT0      = 0000000;
+    enum   VT1      = 0040000;
+    enum FFDLY      = 0100000;
+    enum   FF0      = 0000000;
+    enum   FF1      = 0100000;
+
+    pid_t   tcgetsid(int);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/time.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,270 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.time;
+
+private import core.sys.posix.config;
+public import core.stdc.time;
+public import core.sys.posix.sys.types;
+public import core.sys.posix.signal; // for sigevent
+
+extern (C):
+
+//
+// Required (defined in core.stdc.time)
+//
+/*
+char* asctime(in tm*);
+clock_t clock();
+char* ctime(in time_t*);
+double difftime(time_t, time_t);
+tm* gmtime(in time_t*);
+tm* localtime(in time_t*);
+time_t mktime(tm*);
+size_t strftime(char*, size_t, in char*, in tm*);
+time_t time(time_t*);
+*/
+
+version( linux )
+{
+    time_t timegm(tm*); // non-standard
+}
+else version( OSX )
+{
+    time_t timegm(tm*); // non-standard
+}
+else version( freebsd )
+{
+    time_t timegm(tm*); // non-standard
+}
+
+//
+// C Extension (CX)
+// (defined in core.stdc.time)
+//
+/*
+char* tzname[];
+void tzset();
+*/
+
+//
+// Process CPU-Time Clocks (CPT)
+//
+/*
+int clock_getcpuclockid(pid_t, clockid_t*);
+*/
+
+//
+// Clock Selection (CS)
+//
+/*
+int clock_nanosleep(clockid_t, int, in timespec*, timespec*);
+*/
+
+//
+// Monotonic Clock (MON)
+//
+/*
+CLOCK_MONOTONIC
+*/
+
+//
+// Timer (TMR)
+//
+/*
+CLOCK_PROCESS_CPUTIME_ID (TMR|CPT)
+CLOCK_THREAD_CPUTIME_ID (TMR|TCT)
+
+NOTE: timespec must be defined in core.sys.posix.signal to break
+      a circular import.
+
+struct timespec
+{
+    time_t  tv_sec;
+    int     tv_nsec;
+}
+
+struct itimerspec
+{
+    timespec it_interval;
+    timespec it_value;
+}
+
+CLOCK_REALTIME
+TIMER_ABSTIME
+
+clockid_t
+timer_t
+
+int clock_getres(clockid_t, timespec*);
+int clock_gettime(clockid_t, timespec*);
+int clock_settime(clockid_t, in timespec*);
+int nanosleep(in timespec*, timespec*);
+int timer_create(clockid_t, sigevent*, timer_t*);
+int timer_delete(timer_t);
+int timer_gettime(timer_t, itimerspec*);
+int timer_getoverrun(timer_t);
+int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+*/
+
+version( linux )
+{
+    enum CLOCK_PROCESS_CPUTIME_ID   = 2; // (TMR|CPT)
+    enum CLOCK_THREAD_CPUTIME_ID    = 3; // (TMR|TCT)
+
+    // NOTE: See above for why this is commented out.
+    //
+    //struct timespec
+    //{
+    //    time_t  tv_sec;
+    //    c_long  tv_nsec;
+    //}
+
+    struct itimerspec
+    {
+        timespec it_interval;
+        timespec it_value;
+    }
+
+    enum CLOCK_REALTIME     = 0;
+    enum TIMER_ABSTIME      = 0x01;
+
+    alias int clockid_t;
+    alias int timer_t;
+
+    int clock_getres(clockid_t, timespec*);
+    //int clock_gettime(clockid_t, timespec*);
+    //int clock_settime(clockid_t, in timespec*);
+    int nanosleep(in timespec*, timespec*);
+    int timer_create(clockid_t, sigevent*, timer_t*);
+    int timer_delete(timer_t);
+    int timer_gettime(timer_t, itimerspec*);
+    int timer_getoverrun(timer_t);
+    int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+}
+else version( OSX )
+{
+    int nanosleep(in timespec*, timespec*);
+}
+else version( freebsd )
+{
+    enum CLOCK_PROCESS_CPUTIME_ID   = 2; // (TMR|CPT)
+    enum CLOCK_THREAD_CPUTIME_ID    = 3; // (TMR|TCT)
+
+    // NOTE: See above for why this is commented out.
+    //
+    //struct timespec
+    //{
+    //    time_t  tv_sec;
+    //    c_long  tv_nsec;
+    //}
+
+    struct itimerspec
+    {
+        timespec it_interval;
+        timespec it_value;
+    }
+
+    enum CLOCK_REALTIME     = 0;
+    enum TIMER_ABSTIME      = 0x01;
+
+    //alias int clockid_t;
+    alias int timer_t;
+
+    int clock_getres(clockid_t, timespec*);
+    int clock_gettime(clockid_t, timespec*);
+    int clock_settime(clockid_t, in timespec*);
+    int nanosleep(in timespec*, timespec*);
+    int timer_create(clockid_t, sigevent*, timer_t*);
+    int timer_delete(timer_t);
+    int timer_gettime(timer_t, itimerspec*);
+    int timer_getoverrun(timer_t);
+    int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+}
+
+
+//
+// Thread-Safe Functions (TSF)
+//
+/*
+char* asctime_r(in tm*, char*);
+char* ctime_r(in time_t*, char*);
+tm*   gmtime_r(in time_t*, tm*);
+tm*   localtime_r(in time_t*, tm*);
+*/
+
+version( linux )
+{
+    char* asctime_r(in tm*, char*);
+    char* ctime_r(in time_t*, char*);
+    tm*   gmtime_r(in time_t*, tm*);
+    tm*   localtime_r(in time_t*, tm*);
+}
+else version( OSX )
+{
+    char* asctime_r(in tm*, char*);
+    char* ctime_r(in time_t*, char*);
+    tm*   gmtime_r(in time_t*, tm*);
+    tm*   localtime_r(in time_t*, tm*);
+}
+else version( freebsd )
+{
+    char* asctime_r(in tm*, char*);
+    char* ctime_r(in time_t*, char*);
+    tm*   gmtime_r(in time_t*, tm*);
+    tm*   localtime_r(in time_t*, tm*);
+}
+
+//
+// XOpen (XSI)
+//
+/*
+getdate_err
+
+int daylight;
+int timezone;
+
+tm* getdate(in char*);
+char* strptime(in char*, in char*, tm*);
+*/
+
+version( linux )
+{
+    extern __gshared int    daylight;
+    extern __gshared c_long timezone;
+
+    tm*   getdate(in char*);
+    char* strptime(in char*, in char*, tm*);
+}
+else version( OSX )
+{
+    extern __gshared c_long timezone;
+
+    tm*   getdate(in char*);
+    char* strptime(in char*, in char*, tm*);
+}
+else version( FreeBSD )
+{
+    extern __gshared c_long timezone;
+
+    //tm*   getdate(in char*);
+    char* strptime(in char*, in char*, tm*);
+}
+else version( Solaris )
+{
+    extern __gshared c_long timezone;
+
+    //tm*   getdate(in char*);
+    char* strptime(in char*, in char*, tm*);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/ucontext.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,160 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.ucontext;
+
+private import core.sys.posix.config;
+public import core.sys.posix.signal; // for sigset_t, stack_t
+
+extern (C):
+
+//
+// XOpen (XSI)
+//
+/*
+mcontext_t
+
+struct ucontext_t
+{
+    ucontext_t* uc_link;
+    sigset_t    uc_sigmask;
+    stack_t     uc_stack;
+    mcontext_t  uc_mcontext;
+}
+*/
+
+version( linux )
+{
+
+    version( X86_64 )
+    {
+        private
+        {
+            struct _libc_fpxreg
+            {
+                ushort[4] significand;
+                ushort    exponent;
+                ushort[3] padding;
+            }
+
+            struct _libc_xmmreg
+            {
+                uint[4] element;
+            }
+
+            struct _libc_fpstate
+            {
+                ushort           cwd;
+                ushort           swd;
+                ushort           ftw;
+                ushort           fop;
+                ulong            rip;
+                ulong            rdp;
+                uint             mxcsr;
+                uint             mxcr_mask;
+                _libc_fpxreg[8]  _st;
+                _libc_xmmreg[16] _xmm;
+                uint[24]         padding;
+            }
+
+            enum NGREG = 23;
+
+            alias c_long            greg_t;
+            alias greg_t[NGREG]     gregset_t;
+            alias _libc_fpstate*    fpregset_t;
+        }
+
+        struct mcontext_t
+        {
+            gregset_t   gregs;
+            fpregset_t  fpregs;
+            c_ulong[8]  __reserved1;
+        }
+
+        struct ucontext_t
+        {
+            c_ulong         uc_flags;
+            ucontext_t*     uc_link;
+            stack_t         uc_stack;
+            mcontext_t      uc_mcontext;
+            sigset_t        uc_sigmask;
+            _libc_fpstate   __fpregs_mem;
+        }
+    }
+    else version( X86 )
+    {
+        private
+        {
+            struct _libc_fpreg
+            {
+              ushort[4] significand;
+              ushort    exponent;
+            }
+
+            struct _libc_fpstate
+            {
+              c_ulong           cw;
+              c_ulong           sw;
+              c_ulong           tag;
+              c_ulong           ipoff;
+              c_ulong           cssel;
+              c_ulong           dataoff;
+              c_ulong           datasel;
+              _libc_fpreg[8]    _st;
+              c_ulong           status;
+            }
+
+            enum NGREG = 19;
+
+            alias int               greg_t;
+            alias greg_t[NGREG]     gregset_t;
+            alias _libc_fpstate*    fpregset_t;
+        }
+
+        struct mcontext_t
+        {
+            gregset_t   gregs;
+            fpregset_t  fpregs;
+            c_ulong     oldmask;
+            c_ulong     cr2;
+        }
+
+        struct ucontext_t
+        {
+            c_ulong         uc_flags;
+            ucontext_t*     uc_link;
+            stack_t         uc_stack;
+            mcontext_t      uc_mcontext;
+            sigset_t        uc_sigmask;
+            _libc_fpstate   __fpregs_mem;
+        }
+    }
+}
+
+//
+// Obsolescent (OB)
+//
+/*
+int  getcontext(ucontext_t*);
+void makecontext(ucontext_t*, void function(), int, ...);
+int  setcontext(in ucontext_t*);
+int  swapcontext(ucontext_t*, in ucontext_t*);
+*/
+
+static if( is( ucontext_t ) )
+{
+    int  getcontext(ucontext_t*);
+    void makecontext(ucontext_t*, void function(), int, ...);
+    int  setcontext(in ucontext_t*);
+    int  swapcontext(ucontext_t*, in ucontext_t*);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/unistd.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,599 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.unistd;
+
+private import core.sys.posix.config;
+private import core.stdc.stddef;
+public import core.sys.posix.inttypes;  // for intptr_t
+public import core.sys.posix.sys.types; // for size_t, ssize_t, uid_t, gid_t, off_t, pid_t, useconds_t
+
+extern (C):
+
+enum STDIN_FILENO  = 0;
+enum STDOUT_FILENO = 1;
+enum STDERR_FILENO = 2;
+
+char*   optarg;
+int     optind;
+int     opterr;
+int     optopt;
+
+int     access(in char*, int);
+uint    alarm(uint);
+int     chdir(in char*);
+int     chown(in char*, uid_t, gid_t);
+int     close(int);
+size_t  confstr(int, char*, size_t);
+int     dup(int);
+int     dup2(int, int);
+int     execl(in char*, in char*, ...);
+int     execle(in char*, in char*, ...);
+int     execlp(in char*, in char*, ...);
+int     execv(in char*, in char**);
+int     execve(in char*, in char**, in char**);
+int     execvp(in char*, in char**);
+void    _exit(int);
+int     fchown(int, uid_t, gid_t);
+pid_t   fork();
+c_long  fpathconf(int, int);
+//int     ftruncate(int, off_t);
+char*   getcwd(char*, size_t);
+gid_t   getegid();
+uid_t   geteuid();
+gid_t   getgid();
+int     getgroups(int, gid_t *);
+int     gethostname(char*, size_t);
+char*   getlogin();
+int     getlogin_r(char*, size_t);
+int     getopt(int, in char**, in char*);
+pid_t   getpgrp();
+pid_t   getpid();
+pid_t   getppid();
+uid_t   getuid();
+int     isatty(int);
+int     link(in char*, in char*);
+//off_t   lseek(int, off_t, int);
+c_long  pathconf(in char*, int);
+int     pause();
+int     pipe(int[2]);
+ssize_t read(int, void*, size_t);
+ssize_t readlink(in char*, char*, size_t);
+int     rmdir(in char*);
+int     setegid(gid_t);
+int     seteuid(uid_t);
+int     setgid(gid_t);
+int     setpgid(pid_t, pid_t);
+pid_t   setsid();
+int     setuid(uid_t);
+uint    sleep(uint);
+int     symlink(in char*, in char*);
+c_long  sysconf(int);
+pid_t   tcgetpgrp(int);
+int     tcsetpgrp(int, pid_t);
+char*   ttyname(int);
+int     ttyname_r(int, char*, size_t);
+int     unlink(in char*);
+ssize_t write(int, in void*, size_t);
+
+version( linux )
+{
+  static if( __USE_FILE_OFFSET64 )
+  {
+    off_t lseek64(int, off_t, int);
+    alias lseek64 lseek;
+  }
+  else
+  {
+    off_t lseek(int, off_t, int);
+  }
+  static if( __USE_LARGEFILE64 )
+  {
+    int   ftruncate64(int, off_t);
+    alias ftruncate64 ftruncate;
+  }
+  else
+  {
+    int   ftruncate(int, off_t);
+  }
+}
+else version( freebsd )
+{
+    off_t lseek(int, off_t, int);
+    int   ftruncate(int, off_t);
+}
+else
+{
+    off_t lseek(int, off_t, int);
+    int   ftruncate(int, off_t);
+}
+
+version( linux )
+{
+    enum F_OK       = 0;
+    enum R_OK       = 4;
+    enum W_OK       = 2;
+    enum X_OK       = 1;
+
+    enum F_ULOCK    = 0;
+    enum F_LOCK     = 1;
+    enum F_TLOCK    = 2;
+    enum F_TEST     = 3;
+
+    enum
+    {
+        _CS_PATH,
+
+        _CS_V6_WIDTH_RESTRICTED_ENVS,
+
+        _CS_GNU_LIBC_VERSION,
+        _CS_GNU_LIBPTHREAD_VERSION,
+
+        _CS_LFS_CFLAGS = 1000,
+        _CS_LFS_LDFLAGS,
+        _CS_LFS_LIBS,
+        _CS_LFS_LINTFLAGS,
+        _CS_LFS64_CFLAGS,
+        _CS_LFS64_LDFLAGS,
+        _CS_LFS64_LIBS,
+        _CS_LFS64_LINTFLAGS,
+
+        _CS_XBS5_ILP32_OFF32_CFLAGS = 1100,
+        _CS_XBS5_ILP32_OFF32_LDFLAGS,
+        _CS_XBS5_ILP32_OFF32_LIBS,
+        _CS_XBS5_ILP32_OFF32_LINTFLAGS,
+        _CS_XBS5_ILP32_OFFBIG_CFLAGS,
+        _CS_XBS5_ILP32_OFFBIG_LDFLAGS,
+        _CS_XBS5_ILP32_OFFBIG_LIBS,
+        _CS_XBS5_ILP32_OFFBIG_LINTFLAGS,
+        _CS_XBS5_LP64_OFF64_CFLAGS,
+        _CS_XBS5_LP64_OFF64_LDFLAGS,
+        _CS_XBS5_LP64_OFF64_LIBS,
+        _CS_XBS5_LP64_OFF64_LINTFLAGS,
+        _CS_XBS5_LPBIG_OFFBIG_CFLAGS,
+        _CS_XBS5_LPBIG_OFFBIG_LDFLAGS,
+        _CS_XBS5_LPBIG_OFFBIG_LIBS,
+        _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS,
+
+        _CS_POSIX_V6_ILP32_OFF32_CFLAGS,
+        _CS_POSIX_V6_ILP32_OFF32_LDFLAGS,
+        _CS_POSIX_V6_ILP32_OFF32_LIBS,
+        _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS,
+        _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS,
+        _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS,
+        _CS_POSIX_V6_ILP32_OFFBIG_LIBS,
+        _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS,
+        _CS_POSIX_V6_LP64_OFF64_CFLAGS,
+        _CS_POSIX_V6_LP64_OFF64_LDFLAGS,
+        _CS_POSIX_V6_LP64_OFF64_LIBS,
+        _CS_POSIX_V6_LP64_OFF64_LINTFLAGS,
+        _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS,
+        _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS,
+        _CS_POSIX_V6_LPBIG_OFFBIG_LIBS,
+        _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS
+    }
+
+    enum
+    {
+        _PC_LINK_MAX,
+        _PC_MAX_CANON,
+        _PC_MAX_INPUT,
+        _PC_NAME_MAX,
+        _PC_PATH_MAX,
+        _PC_PIPE_BUF,
+        _PC_CHOWN_RESTRICTED,
+        _PC_NO_TRUNC,
+        _PC_VDISABLE,
+        _PC_SYNC_IO,
+        _PC_ASYNC_IO,
+        _PC_PRIO_IO,
+        _PC_SOCK_MAXBUF,
+        _PC_FILESIZEBITS,
+        _PC_REC_INCR_XFER_SIZE,
+        _PC_REC_MAX_XFER_SIZE,
+        _PC_REC_MIN_XFER_SIZE,
+        _PC_REC_XFER_ALIGN,
+        _PC_ALLOC_SIZE_MIN,
+        _PC_SYMLINK_MAX,
+        _PC_2_SYMLINKS
+    }
+
+    enum
+    {
+        _SC_ARG_MAX,
+        _SC_CHILD_MAX,
+        _SC_CLK_TCK,
+        _SC_NGROUPS_MAX,
+        _SC_OPEN_MAX,
+        _SC_STREAM_MAX,
+        _SC_TZNAME_MAX,
+        _SC_JOB_CONTROL,
+        _SC_SAVED_IDS,
+        _SC_REALTIME_SIGNALS,
+        _SC_PRIORITY_SCHEDULING,
+        _SC_TIMERS,
+        _SC_ASYNCHRONOUS_IO,
+        _SC_PRIORITIZED_IO,
+        _SC_SYNCHRONIZED_IO,
+        _SC_FSYNC,
+        _SC_MAPPED_FILES,
+        _SC_MEMLOCK,
+        _SC_MEMLOCK_RANGE,
+        _SC_MEMORY_PROTECTION,
+        _SC_MESSAGE_PASSING,
+        _SC_SEMAPHORES,
+        _SC_SHARED_MEMORY_OBJECTS,
+        _SC_AIO_LISTIO_MAX,
+        _SC_AIO_MAX,
+        _SC_AIO_PRIO_DELTA_MAX,
+        _SC_DELAYTIMER_MAX,
+        _SC_MQ_OPEN_MAX,
+        _SC_MQ_PRIO_MAX,
+        _SC_VERSION,
+        _SC_PAGESIZE,
+        _SC_PAGE_SIZE = _SC_PAGESIZE,
+        _SC_RTSIG_MAX,
+        _SC_SEM_NSEMS_MAX,
+        _SC_SEM_VALUE_MAX,
+        _SC_SIGQUEUE_MAX,
+        _SC_TIMER_MAX,
+
+        _SC_BC_BASE_MAX,
+        _SC_BC_DIM_MAX,
+        _SC_BC_SCALE_MAX,
+        _SC_BC_STRING_MAX,
+        _SC_COLL_WEIGHTS_MAX,
+        _SC_EQUIV_CLASS_MAX,
+        _SC_EXPR_NEST_MAX,
+        _SC_LINE_MAX,
+        _SC_RE_DUP_MAX,
+        _SC_CHARCLASS_NAME_MAX,
+
+        _SC_2_VERSION,
+        _SC_2_C_BIND,
+        _SC_2_C_DEV,
+        _SC_2_FORT_DEV,
+        _SC_2_FORT_RUN,
+        _SC_2_SW_DEV,
+        _SC_2_LOCALEDEF,
+
+        _SC_PII,
+        _SC_PII_XTI,
+        _SC_PII_SOCKET,
+        _SC_PII_INTERNET,
+        _SC_PII_OSI,
+        _SC_POLL,
+        _SC_SELECT,
+        _SC_UIO_MAXIOV,
+        _SC_IOV_MAX = _SC_UIO_MAXIOV,
+        _SC_PII_INTERNET_STREAM,
+        _SC_PII_INTERNET_DGRAM,
+        _SC_PII_OSI_COTS,
+        _SC_PII_OSI_CLTS,
+        _SC_PII_OSI_M,
+        _SC_T_IOV_MAX,
+
+        _SC_THREADS,
+        _SC_THREAD_SAFE_FUNCTIONS,
+        _SC_GETGR_R_SIZE_MAX,
+        _SC_GETPW_R_SIZE_MAX,
+        _SC_LOGIN_NAME_MAX,
+        _SC_TTY_NAME_MAX,
+        _SC_THREAD_DESTRUCTOR_ITERATIONS,
+        _SC_THREAD_KEYS_MAX,
+        _SC_THREAD_STACK_MIN,
+        _SC_THREAD_THREADS_MAX,
+        _SC_THREAD_ATTR_STACKADDR,
+        _SC_THREAD_ATTR_STACKSIZE,
+        _SC_THREAD_PRIORITY_SCHEDULING,
+        _SC_THREAD_PRIO_INHERIT,
+        _SC_THREAD_PRIO_PROTECT,
+        _SC_THREAD_PROCESS_SHARED,
+
+        _SC_NPROCESSORS_CONF,
+        _SC_NPROCESSORS_ONLN,
+        _SC_PHYS_PAGES,
+        _SC_AVPHYS_PAGES,
+        _SC_ATEXIT_MAX,
+        _SC_PASS_MAX,
+
+        _SC_XOPEN_VERSION,
+        _SC_XOPEN_XCU_VERSION,
+        _SC_XOPEN_UNIX,
+        _SC_XOPEN_CRYPT,
+        _SC_XOPEN_ENH_I18N,
+        _SC_XOPEN_SHM,
+
+        _SC_2_CHAR_TERM,
+        _SC_2_C_VERSION,
+        _SC_2_UPE,
+
+        _SC_XOPEN_XPG2,
+        _SC_XOPEN_XPG3,
+        _SC_XOPEN_XPG4,
+
+        _SC_CHAR_BIT,
+        _SC_CHAR_MAX,
+        _SC_CHAR_MIN,
+        _SC_INT_MAX,
+        _SC_INT_MIN,
+        _SC_LONG_BIT,
+        _SC_WORD_BIT,
+        _SC_MB_LEN_MAX,
+        _SC_NZERO,
+        _SC_SSIZE_MAX,
+        _SC_SCHAR_MAX,
+        _SC_SCHAR_MIN,
+        _SC_SHRT_MAX,
+        _SC_SHRT_MIN,
+        _SC_UCHAR_MAX,
+        _SC_UINT_MAX,
+        _SC_ULONG_MAX,
+        _SC_USHRT_MAX,
+
+        _SC_NL_ARGMAX,
+        _SC_NL_LANGMAX,
+        _SC_NL_MSGMAX,
+        _SC_NL_NMAX,
+        _SC_NL_SETMAX,
+        _SC_NL_TEXTMAX,
+
+        _SC_XBS5_ILP32_OFF32,
+        _SC_XBS5_ILP32_OFFBIG,
+        _SC_XBS5_LP64_OFF64,
+        _SC_XBS5_LPBIG_OFFBIG,
+
+        _SC_XOPEN_LEGACY,
+        _SC_XOPEN_REALTIME,
+        _SC_XOPEN_REALTIME_THREADS,
+
+        _SC_ADVISORY_INFO,
+        _SC_BARRIERS,
+        _SC_BASE,
+        _SC_C_LANG_SUPPORT,
+        _SC_C_LANG_SUPPORT_R,
+        _SC_CLOCK_SELECTION,
+        _SC_CPUTIME,
+        _SC_THREAD_CPUTIME,
+        _SC_DEVICE_IO,
+        _SC_DEVICE_SPECIFIC,
+        _SC_DEVICE_SPECIFIC_R,
+        _SC_FD_MGMT,
+        _SC_FIFO,
+        _SC_PIPE,
+        _SC_FILE_ATTRIBUTES,
+        _SC_FILE_LOCKING,
+        _SC_FILE_SYSTEM,
+        _SC_MONOTONIC_CLOCK,
+        _SC_MULTI_PROCESS,
+        _SC_SINGLE_PROCESS,
+        _SC_NETWORKING,
+        _SC_READER_WRITER_LOCKS,
+        _SC_SPIN_LOCKS,
+        _SC_REGEXP,
+        _SC_REGEX_VERSION,
+        _SC_SHELL,
+        _SC_SIGNALS,
+        _SC_SPAWN,
+        _SC_SPORADIC_SERVER,
+        _SC_THREAD_SPORADIC_SERVER,
+        _SC_SYSTEM_DATABASE,
+        _SC_SYSTEM_DATABASE_R,
+        _SC_TIMEOUTS,
+        _SC_TYPED_MEMORY_OBJECTS,
+        _SC_USER_GROUPS,
+        _SC_USER_GROUPS_R,
+        _SC_2_PBS,
+        _SC_2_PBS_ACCOUNTING,
+        _SC_2_PBS_LOCATE,
+        _SC_2_PBS_MESSAGE,
+        _SC_2_PBS_TRACK,
+        _SC_SYMLOOP_MAX,
+        _SC_STREAMS,
+        _SC_2_PBS_CHECKPOINT,
+
+        _SC_V6_ILP32_OFF32,
+        _SC_V6_ILP32_OFFBIG,
+        _SC_V6_LP64_OFF64,
+        _SC_V6_LPBIG_OFFBIG,
+
+        _SC_HOST_NAME_MAX,
+        _SC_TRACE,
+        _SC_TRACE_EVENT_FILTER,
+        _SC_TRACE_INHERIT,
+        _SC_TRACE_LOG,
+
+        _SC_LEVEL1_ICACHE_SIZE,
+        _SC_LEVEL1_ICACHE_ASSOC,
+        _SC_LEVEL1_ICACHE_LINESIZE,
+        _SC_LEVEL1_DCACHE_SIZE,
+        _SC_LEVEL1_DCACHE_ASSOC,
+        _SC_LEVEL1_DCACHE_LINESIZE,
+        _SC_LEVEL2_CACHE_SIZE,
+        _SC_LEVEL2_CACHE_ASSOC,
+        _SC_LEVEL2_CACHE_LINESIZE,
+        _SC_LEVEL3_CACHE_SIZE,
+        _SC_LEVEL3_CACHE_ASSOC,
+        _SC_LEVEL3_CACHE_LINESIZE,
+        _SC_LEVEL4_CACHE_SIZE,
+        _SC_LEVEL4_CACHE_ASSOC,
+        _SC_LEVEL4_CACHE_LINESIZE,
+
+        _SC_IPV6 = _SC_LEVEL1_ICACHE_SIZE + 50,
+        _SC_RAW_SOCKETS
+    }
+}
+else version( OSX )
+{
+    enum F_OK       = 0;
+    enum R_OK       = 4;
+    enum W_OK       = 2;
+    enum X_OK       = 1;
+
+    enum F_ULOCK    = 0;
+    enum F_LOCK     = 1;
+    enum F_TLOCK    = 2;
+    enum F_TEST     = 3;
+}
+else version( freebsd )
+{
+    enum F_OK       = 0;
+    enum R_OK       = 0x04;
+    enum W_OK       = 0x02;
+    enum X_OK       = 0x01;
+
+    enum F_ULOCK    = 0;
+    enum F_LOCK     = 1;
+    enum F_TLOCK    = 2;
+    enum F_TEST     = 3;
+}
+
+//
+// File Synchronization (FSC)
+//
+/*
+int fsync(int);
+*/
+
+//
+// Synchronized I/O (SIO)
+//
+/*
+int fdatasync(int);
+*/
+
+//
+// XOpen (XSI)
+//
+/*
+char*      crypt(in char*, in char*);
+char*      ctermid(char*);
+void       encrypt(char[64], int);
+int        fchdir(int);
+c_long     gethostid();
+pid_t      getpgid(pid_t);
+pid_t      getsid(pid_t);
+char*      getwd(char*); // LEGACY
+int        lchown(in char*, uid_t, gid_t);
+int        lockf(int, int, off_t);
+int        nice(int);
+ssize_t    pread(int, void*, size_t, off_t);
+ssize_t    pwrite(int, in void*, size_t, off_t);
+pid_t      setpgrp();
+int        setregid(gid_t, gid_t);
+int        setreuid(uid_t, uid_t);
+void       swab(in void*, void*, ssize_t);
+void       sync();
+int        truncate(in char*, off_t);
+useconds_t ualarm(useconds_t, useconds_t);
+int        usleep(useconds_t);
+pid_t      vfork();
+*/
+
+version( linux )
+{
+    char*      crypt(in char*, in char*);
+    char*      ctermid(char*);
+    void       encrypt(char[64], int);
+    int        fchdir(int);
+    c_long     gethostid();
+    pid_t      getpgid(pid_t);
+    pid_t      getsid(pid_t);
+    char*      getwd(char*); // LEGACY
+    int        lchown(in char*, uid_t, gid_t);
+    //int        lockf(int, int, off_t);
+    int        nice(int);
+    //ssize_t    pread(int, void*, size_t, off_t);
+    //ssize_t    pwrite(int, in void*, size_t, off_t);
+    pid_t      setpgrp();
+    int        setregid(gid_t, gid_t);
+    int        setreuid(uid_t, uid_t);
+    void       swab(in void*, void*, ssize_t);
+    void       sync();
+    //int        truncate(in char*, off_t);
+    useconds_t ualarm(useconds_t, useconds_t);
+    int        usleep(useconds_t);
+    pid_t      vfork();
+
+  static if( __USE_LARGEFILE64 )
+  {
+    int        lockf64(int, int, off_t);
+    alias      lockf64 lockf;
+
+    ssize_t    pread64(int, void*, size_t, off_t);
+    alias      pread64 pread;
+
+    ssize_t    pwrite64(int, in void*, size_t, off_t);
+    alias      pwrite64 pwrite;
+
+    int        truncate64(in char*, off_t);
+    alias      truncate64 truncate;
+  }
+  else
+  {
+    int        lockf(int, int, off_t);
+    ssize_t    pread(int, void*, size_t, off_t);
+    ssize_t    pwrite(int, in void*, size_t, off_t);
+    int        truncate(in char*, off_t);
+  }
+}
+else version( OSX )
+{
+    char*      crypt(in char*, in char*);
+    char*      ctermid(char*);
+    void       encrypt(char[64], int);
+    int        fchdir(int);
+    c_long     gethostid();
+    pid_t      getpgid(pid_t);
+    pid_t      getsid(pid_t);
+    char*      getwd(char*); // LEGACY
+    int        lchown(in char*, uid_t, gid_t);
+    int        lockf(int, int, off_t);
+    int        nice(int);
+    ssize_t    pread(int, void*, size_t, off_t);
+    ssize_t    pwrite(int, in void*, size_t, off_t);
+    pid_t      setpgrp();
+    int        setregid(gid_t, gid_t);
+    int        setreuid(uid_t, uid_t);
+    void       swab(in void*, void*, ssize_t);
+    void       sync();
+    int        truncate(in char*, off_t);
+    useconds_t ualarm(useconds_t, useconds_t);
+    int        usleep(useconds_t);
+    pid_t      vfork();
+}
+else version (freebsd)
+{
+    char*      crypt(in char*, in char*);
+    //char*      ctermid(char*);
+    void       encrypt(char*, int);
+    int        fchdir(int);
+    c_long     gethostid();
+    int        getpgid(pid_t);
+    int        getsid(pid_t);
+    char*      getwd(char*); // LEGACY
+    int        lchown(in char*, uid_t, gid_t);
+    int        lockf(int, int, off_t);
+    int        nice(int);
+    ssize_t    pread(int, void*, size_t, off_t);
+    ssize_t    pwrite(int, in void*, size_t, off_t);
+    int        setpgrp(pid_t, pid_t);
+    int        setregid(gid_t, gid_t);
+    int        setreuid(uid_t, uid_t);
+    void       swab(in void*, void*, ssize_t);
+    void       sync();
+    int        truncate(in char*, off_t);
+    useconds_t ualarm(useconds_t, useconds_t);
+    int        usleep(useconds_t);
+    pid_t      vfork();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/posix/utime.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,63 @@
+/**
+ * D header file for POSIX.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.posix.utime;
+
+private import core.sys.posix.config;
+public import core.sys.posix.sys.types; // for time_t
+
+extern (C):
+
+//
+// Required
+//
+/*
+struct utimbuf
+{
+    time_t  actime;
+    time_t  modtime;
+}
+
+int utime(in char*, in utimbuf*);
+*/
+
+version( linux )
+{
+    struct utimbuf
+    {
+        time_t  actime;
+        time_t  modtime;
+    }
+
+    int utime(in char*, in utimbuf*);
+}
+else version( OSX )
+{
+    struct utimbuf
+    {
+        time_t  actime;
+        time_t  modtime;
+    }
+
+    int utime(in char*, in utimbuf*);
+}
+else version( freebsd )
+{
+    struct utimbuf
+    {
+        time_t  actime;
+        time_t  modtime;
+    }
+
+    int utime(in char*, in utimbuf*);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/core/sys/windows/windows.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,3181 @@
+/**
+ *  Windows is a registered trademark of Microsoft Corporation in the United
+ *  States and other countries.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sys.windows.windows;
+
+version (Windows)
+{
+}
+else
+{
+    static assert(0);       // Windows only
+}
+
+extern (Windows)
+{
+    alias uint ULONG;
+    alias ULONG *PULONG;
+    alias ushort USHORT;
+    alias USHORT *PUSHORT;
+    alias ubyte UCHAR;
+    alias UCHAR *PUCHAR;
+    alias char *PSZ;
+    alias wchar WCHAR;
+
+    alias void VOID;
+    alias char CHAR;
+    alias short SHORT;
+    alias int LONG;
+    alias CHAR *LPSTR;
+    alias CHAR *PSTR;
+
+    alias const(CHAR)* LPCSTR;
+    alias const(CHAR)* PCSTR;
+
+    alias LPSTR LPTCH, PTCH;
+    alias LPSTR PTSTR, LPTSTR;
+    alias LPCSTR LPCTSTR;
+
+    alias WCHAR* LPWSTR;
+
+    alias const(WCHAR)* LPCWSTR, PCWSTR;
+
+    alias uint DWORD;
+    alias int BOOL;
+    alias ubyte BYTE;
+    alias ushort WORD;
+    alias float FLOAT;
+    alias FLOAT *PFLOAT;
+    alias BOOL *PBOOL;
+    alias BOOL *LPBOOL;
+    alias BYTE *PBYTE;
+    alias BYTE *LPBYTE;
+    alias int *PINT;
+    alias int *LPINT;
+    alias WORD *PWORD;
+    alias WORD *LPWORD;
+    alias int *LPLONG;
+    alias DWORD *PDWORD;
+    alias DWORD *LPDWORD;
+    alias void *LPVOID;
+    alias void *LPCVOID;
+
+    alias int INT;
+    alias uint UINT;
+    alias uint *PUINT;
+
+// ULONG_PTR must be able to store a pointer as an integral type
+version(Win64)
+{
+    alias  long INT_PTR;
+    alias ulong UINT_PTR;
+    alias  long LONG_PTR;
+    alias ulong ULONG_PTR;
+    alias  long * PINT_PTR;
+    alias ulong * PUINT_PTR;
+    alias  long * PLONG_PTR;
+    alias ulong * PULONG_PTR;
+}
+version(Win32)
+{
+    alias  int INT_PTR;
+    alias uint UINT_PTR;
+    alias  int LONG_PTR;
+    alias uint ULONG_PTR;
+    alias  int * PINT_PTR;
+    alias uint * PUINT_PTR;
+    alias  int * PLONG_PTR;
+    alias uint * PULONG_PTR;
+}
+
+    typedef void *HANDLE;
+    alias void *PVOID;
+    alias HANDLE HGLOBAL;
+    alias HANDLE HLOCAL;
+    alias LONG HRESULT;
+    alias LONG SCODE;
+    alias HANDLE HINSTANCE;
+    alias HINSTANCE HMODULE;
+    alias HANDLE HWND;
+
+    alias HANDLE HGDIOBJ;
+    alias HANDLE HACCEL;
+    alias HANDLE HBITMAP;
+    alias HANDLE HBRUSH;
+    alias HANDLE HCOLORSPACE;
+    alias HANDLE HDC;
+    alias HANDLE HGLRC;
+    alias HANDLE HDESK;
+    alias HANDLE HENHMETAFILE;
+    alias HANDLE HFONT;
+    alias HANDLE HICON;
+    alias HANDLE HMENU;
+    alias HANDLE HMETAFILE;
+    alias HANDLE HPALETTE;
+    alias HANDLE HPEN;
+    alias HANDLE HRGN;
+    alias HANDLE HRSRC;
+    alias HANDLE HSTR;
+    alias HANDLE HTASK;
+    alias HANDLE HWINSTA;
+    alias HANDLE HKL;
+    alias HICON HCURSOR;
+
+    alias HANDLE HKEY;
+    alias HKEY *PHKEY;
+    alias DWORD ACCESS_MASK;
+    alias ACCESS_MASK *PACCESS_MASK;
+    alias ACCESS_MASK REGSAM;
+
+    alias int (*FARPROC)();
+
+    alias UINT WPARAM;
+    alias LONG LPARAM;
+    alias LONG LRESULT;
+
+    alias DWORD   COLORREF;
+    alias DWORD   *LPCOLORREF;
+    alias WORD    ATOM;
+
+version (0)
+{   // Properly prototyped versions
+    alias BOOL function(HWND, UINT, WPARAM, LPARAM) DLGPROC;
+    alias VOID function(HWND, UINT, UINT, DWORD) TIMERPROC;
+    alias BOOL function(HDC, LPARAM, int) GRAYSTRINGPROC;
+    alias BOOL function(HWND, LPARAM) WNDENUMPROC;
+    alias LRESULT function(int code, WPARAM wParam, LPARAM lParam) HOOKPROC;
+    alias VOID function(HWND, UINT, DWORD, LRESULT) SENDASYNCPROC;
+    alias BOOL function(HWND, LPCSTR, HANDLE) PROPENUMPROCA;
+    alias BOOL function(HWND, LPCWSTR, HANDLE) PROPENUMPROCW;
+    alias BOOL function(HWND, LPSTR, HANDLE, DWORD) PROPENUMPROCEXA;
+    alias BOOL function(HWND, LPWSTR, HANDLE, DWORD) PROPENUMPROCEXW;
+    alias int function(LPSTR lpch, int ichCurrent, int cch, int code)
+       EDITWORDBREAKPROCA;
+    alias int function(LPWSTR lpch, int ichCurrent, int cch, int code)
+       EDITWORDBREAKPROCW;
+    alias BOOL function(HDC hdc, LPARAM lData, WPARAM wData, int cx, int cy)
+       DRAWSTATEPROC;
+}
+else
+{
+    alias FARPROC DLGPROC;
+    alias FARPROC TIMERPROC;
+    alias FARPROC GRAYSTRINGPROC;
+    alias FARPROC WNDENUMPROC;
+    alias FARPROC HOOKPROC;
+    alias FARPROC SENDASYNCPROC;
+    alias FARPROC EDITWORDBREAKPROCA;
+    alias FARPROC EDITWORDBREAKPROCW;
+    alias FARPROC PROPENUMPROCA;
+    alias FARPROC PROPENUMPROCW;
+    alias FARPROC PROPENUMPROCEXA;
+    alias FARPROC PROPENUMPROCEXW;
+    alias FARPROC DRAWSTATEPROC;
+}
+
+extern (D)
+{
+WORD HIWORD(int l) { return cast(WORD)((l >> 16) & 0xFFFF); }
+WORD LOWORD(int l) { return cast(WORD)l; }
+bool FAILED(int status) { return status < 0; }
+bool SUCCEEDED(int Status) { return Status >= 0; }
+}
+
+enum : int
+{
+    FALSE = 0,
+    TRUE = 1,
+}
+
+enum : uint
+{
+    MAX_PATH = 260,
+    HINSTANCE_ERROR = 32,
+}
+
+enum
+{
+    ERROR_SUCCESS =                    0,
+    ERROR_INVALID_FUNCTION =           1,
+    ERROR_FILE_NOT_FOUND =             2,
+    ERROR_PATH_NOT_FOUND =             3,
+    ERROR_TOO_MANY_OPEN_FILES =        4,
+    ERROR_ACCESS_DENIED =              5,
+    ERROR_INVALID_HANDLE =             6,
+    ERROR_NO_MORE_FILES =              18,
+    ERROR_MORE_DATA =          234,
+    ERROR_NO_MORE_ITEMS =          259,
+}
+
+enum
+{
+    DLL_PROCESS_ATTACH = 1,
+    DLL_THREAD_ATTACH =  2,
+    DLL_THREAD_DETACH =  3,
+    DLL_PROCESS_DETACH = 0,
+}
+
+enum
+{
+    FILE_BEGIN           = 0,
+    FILE_CURRENT         = 1,
+    FILE_END             = 2,
+}
+
+enum : uint
+{
+    DELETE =                           0x00010000,
+    READ_CONTROL =                     0x00020000,
+    WRITE_DAC =                        0x00040000,
+    WRITE_OWNER =                      0x00080000,
+    SYNCHRONIZE =                      0x00100000,
+
+    STANDARD_RIGHTS_REQUIRED =         0x000F0000,
+    STANDARD_RIGHTS_READ =             READ_CONTROL,
+    STANDARD_RIGHTS_WRITE =            READ_CONTROL,
+    STANDARD_RIGHTS_EXECUTE =          READ_CONTROL,
+    STANDARD_RIGHTS_ALL =              0x001F0000,
+    SPECIFIC_RIGHTS_ALL =              0x0000FFFF,
+    ACCESS_SYSTEM_SECURITY =           0x01000000,
+    MAXIMUM_ALLOWED =                  0x02000000,
+
+    GENERIC_READ                     = 0x80000000,
+    GENERIC_WRITE                    = 0x40000000,
+    GENERIC_EXECUTE                  = 0x20000000,
+    GENERIC_ALL                      = 0x10000000,
+}
+
+enum
+{
+    FILE_SHARE_READ                 = 0x00000001,
+    FILE_SHARE_WRITE                = 0x00000002,
+    FILE_SHARE_DELETE               = 0x00000004,
+    FILE_ATTRIBUTE_READONLY         = 0x00000001,
+    FILE_ATTRIBUTE_HIDDEN           = 0x00000002,
+    FILE_ATTRIBUTE_SYSTEM           = 0x00000004,
+    FILE_ATTRIBUTE_DIRECTORY        = 0x00000010,
+    FILE_ATTRIBUTE_ARCHIVE          = 0x00000020,
+    FILE_ATTRIBUTE_NORMAL           = 0x00000080,
+    FILE_ATTRIBUTE_TEMPORARY        = 0x00000100,
+    FILE_ATTRIBUTE_COMPRESSED       = 0x00000800,
+    FILE_ATTRIBUTE_OFFLINE          = 0x00001000,
+    FILE_NOTIFY_CHANGE_FILE_NAME    = 0x00000001,
+    FILE_NOTIFY_CHANGE_DIR_NAME     = 0x00000002,
+    FILE_NOTIFY_CHANGE_ATTRIBUTES   = 0x00000004,
+    FILE_NOTIFY_CHANGE_SIZE         = 0x00000008,
+    FILE_NOTIFY_CHANGE_LAST_WRITE   = 0x00000010,
+    FILE_NOTIFY_CHANGE_LAST_ACCESS  = 0x00000020,
+    FILE_NOTIFY_CHANGE_CREATION     = 0x00000040,
+    FILE_NOTIFY_CHANGE_SECURITY     = 0x00000100,
+    FILE_ACTION_ADDED               = 0x00000001,
+    FILE_ACTION_REMOVED             = 0x00000002,
+    FILE_ACTION_MODIFIED            = 0x00000003,
+    FILE_ACTION_RENAMED_OLD_NAME    = 0x00000004,
+    FILE_ACTION_RENAMED_NEW_NAME    = 0x00000005,
+    FILE_CASE_SENSITIVE_SEARCH      = 0x00000001,
+    FILE_CASE_PRESERVED_NAMES       = 0x00000002,
+    FILE_UNICODE_ON_DISK            = 0x00000004,
+    FILE_PERSISTENT_ACLS            = 0x00000008,
+    FILE_FILE_COMPRESSION           = 0x00000010,
+    FILE_VOLUME_IS_COMPRESSED       = 0x00008000,
+}
+
+enum : DWORD
+{
+    MAILSLOT_NO_MESSAGE = cast(DWORD)-1,
+    MAILSLOT_WAIT_FOREVER = cast(DWORD)-1,
+}
+
+enum : uint
+{
+    FILE_FLAG_WRITE_THROUGH         = 0x80000000,
+    FILE_FLAG_OVERLAPPED            = 0x40000000,
+    FILE_FLAG_NO_BUFFERING          = 0x20000000,
+    FILE_FLAG_RANDOM_ACCESS         = 0x10000000,
+    FILE_FLAG_SEQUENTIAL_SCAN       = 0x08000000,
+    FILE_FLAG_DELETE_ON_CLOSE       = 0x04000000,
+    FILE_FLAG_BACKUP_SEMANTICS      = 0x02000000,
+    FILE_FLAG_POSIX_SEMANTICS       = 0x01000000,
+}
+
+enum
+{
+    CREATE_NEW          = 1,
+    CREATE_ALWAYS       = 2,
+    OPEN_EXISTING       = 3,
+    OPEN_ALWAYS         = 4,
+    TRUNCATE_EXISTING   = 5,
+}
+
+
+enum
+{
+    HANDLE INVALID_HANDLE_VALUE     = cast(HANDLE)-1,
+    DWORD INVALID_SET_FILE_POINTER  = cast(DWORD)-1,
+    DWORD INVALID_FILE_SIZE         = cast(DWORD)0xFFFFFFFF,
+}
+
+struct OVERLAPPED {
+    DWORD   Internal;
+    DWORD   InternalHigh;
+    DWORD   Offset;
+    DWORD   OffsetHigh;
+    HANDLE  hEvent;
+}
+
+struct SECURITY_ATTRIBUTES {
+    DWORD nLength;
+    void *lpSecurityDescriptor;
+    BOOL bInheritHandle;
+}
+
+alias SECURITY_ATTRIBUTES* PSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES;
+
+struct FILETIME {
+    DWORD dwLowDateTime;
+    DWORD dwHighDateTime;
+}
+alias FILETIME* PFILETIME, LPFILETIME;
+
+struct WIN32_FIND_DATA {
+    DWORD dwFileAttributes;
+    FILETIME ftCreationTime;
+    FILETIME ftLastAccessTime;
+    FILETIME ftLastWriteTime;
+    DWORD nFileSizeHigh;
+    DWORD nFileSizeLow;
+    DWORD dwReserved0;
+    DWORD dwReserved1;
+    char   cFileName[MAX_PATH];
+    char   cAlternateFileName[ 14 ];
+}
+
+struct WIN32_FIND_DATAW {
+    DWORD dwFileAttributes;
+    FILETIME ftCreationTime;
+    FILETIME ftLastAccessTime;
+    FILETIME ftLastWriteTime;
+    DWORD nFileSizeHigh;
+    DWORD nFileSizeLow;
+    DWORD dwReserved0;
+    DWORD dwReserved1;
+    wchar  cFileName[ 260  ];
+    wchar  cAlternateFileName[ 14 ];
+}
+
+// Critical Section
+
+struct _LIST_ENTRY
+{
+    _LIST_ENTRY *Flink;
+    _LIST_ENTRY *Blink;
+}
+alias _LIST_ENTRY LIST_ENTRY;
+
+struct _RTL_CRITICAL_SECTION_DEBUG
+{
+    WORD   Type;
+    WORD   CreatorBackTraceIndex;
+    _RTL_CRITICAL_SECTION *CriticalSection;
+    LIST_ENTRY ProcessLocksList;
+    DWORD EntryCount;
+    DWORD ContentionCount;
+    DWORD Spare[ 2 ];
+}
+alias _RTL_CRITICAL_SECTION_DEBUG RTL_CRITICAL_SECTION_DEBUG;
+
+struct _RTL_CRITICAL_SECTION
+{
+    RTL_CRITICAL_SECTION_DEBUG * DebugInfo;
+
+    //
+    //  The following three fields control entering and exiting the critical
+    //  section for the resource
+    //
+
+    LONG LockCount;
+    LONG RecursionCount;
+    HANDLE OwningThread;        // from the thread's ClientId->UniqueThread
+    HANDLE LockSemaphore;
+    ULONG_PTR SpinCount;        // force size on 64-bit systems when packed
+}
+alias _RTL_CRITICAL_SECTION CRITICAL_SECTION;
+
+
+enum
+{
+    STD_INPUT_HANDLE =    cast(DWORD)-10,
+    STD_OUTPUT_HANDLE =   cast(DWORD)-11,
+    STD_ERROR_HANDLE =    cast(DWORD)-12,
+}
+
+export
+{
+BOOL SetCurrentDirectoryA(LPCSTR lpPathName);
+BOOL SetCurrentDirectoryW(LPCWSTR lpPathName);
+DWORD GetCurrentDirectoryA(DWORD nBufferLength, LPSTR lpBuffer);
+DWORD GetCurrentDirectoryW(DWORD nBufferLength, LPWSTR lpBuffer);
+BOOL CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
+BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
+BOOL CreateDirectoryExA(LPCSTR lpTemplateDirectory, LPCSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
+BOOL CreateDirectoryExW(LPCWSTR lpTemplateDirectory, LPCWSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
+BOOL RemoveDirectoryA(LPCSTR lpPathName);
+BOOL RemoveDirectoryW(LPCWSTR lpPathName);
+
+BOOL   CloseHandle(HANDLE hObject);
+
+HANDLE CreateFileA(in char* lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
+    SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition,
+    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
+HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
+    SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition,
+    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
+
+BOOL   DeleteFileA(in char *lpFileName);
+BOOL   DeleteFileW(LPCWSTR lpFileName);
+
+BOOL   FindClose(HANDLE hFindFile);
+HANDLE FindFirstFileA(in char *lpFileName, WIN32_FIND_DATA* lpFindFileData);
+HANDLE FindFirstFileW(in LPCWSTR lpFileName, WIN32_FIND_DATAW* lpFindFileData);
+BOOL   FindNextFileA(HANDLE hFindFile, WIN32_FIND_DATA* lpFindFileData);
+BOOL   FindNextFileW(HANDLE hFindFile, WIN32_FIND_DATAW* lpFindFileData);
+BOOL   GetExitCodeThread(HANDLE hThread, DWORD *lpExitCode);
+DWORD  GetLastError();
+DWORD  GetFileAttributesA(in char *lpFileName);
+DWORD  GetFileAttributesW(in wchar *lpFileName);
+DWORD  GetFileSize(HANDLE hFile, DWORD *lpFileSizeHigh);
+BOOL   CopyFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, BOOL bFailIfExists);
+BOOL   CopyFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists);
+BOOL   MoveFileA(in char *from, in char *to);
+BOOL   MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName);
+BOOL   ReadFile(HANDLE hFile, void *lpBuffer, DWORD nNumberOfBytesToRead,
+    DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped);
+DWORD  SetFilePointer(HANDLE hFile, LONG lDistanceToMove,
+    LONG *lpDistanceToMoveHigh, DWORD dwMoveMethod);
+BOOL   WriteFile(HANDLE hFile, in void *lpBuffer, DWORD nNumberOfBytesToWrite,
+    DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped);
+DWORD  GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
+HANDLE GetStdHandle(DWORD nStdHandle);
+BOOL   SetStdHandle(DWORD nStdHandle, HANDLE hHandle);
+}
+
+struct MEMORYSTATUS {
+    DWORD dwLength;
+    DWORD dwMemoryLoad;
+    DWORD dwTotalPhys;
+    DWORD dwAvailPhys;
+    DWORD dwTotalPageFile;
+    DWORD dwAvailPageFile;
+    DWORD dwTotalVirtual;
+    DWORD dwAvailVirtual;
+};
+alias MEMORYSTATUS *LPMEMORYSTATUS;
+
+HMODULE LoadLibraryA(LPCSTR lpLibFileName);
+FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName);
+DWORD GetVersion();
+BOOL FreeLibrary(HMODULE hLibModule);
+void FreeLibraryAndExitThread(HMODULE hLibModule, DWORD dwExitCode);
+BOOL DisableThreadLibraryCalls(HMODULE hLibModule);
+
+//
+// Registry Specific Access Rights.
+//
+
+enum
+{
+    KEY_QUERY_VALUE =         0x0001,
+    KEY_SET_VALUE =           0x0002,
+    KEY_CREATE_SUB_KEY =      0x0004,
+    KEY_ENUMERATE_SUB_KEYS =  0x0008,
+    KEY_NOTIFY =              0x0010,
+    KEY_CREATE_LINK =         0x0020,
+
+    KEY_READ =       cast(int)((STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY)   & ~SYNCHRONIZE),
+    KEY_WRITE =      cast(int)((STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY) & ~SYNCHRONIZE),
+    KEY_EXECUTE =    cast(int)(KEY_READ & ~SYNCHRONIZE),
+    KEY_ALL_ACCESS = cast(int)((STANDARD_RIGHTS_ALL | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY | KEY_CREATE_LINK) & ~SYNCHRONIZE),
+}
+
+//
+// Key creation/open disposition
+//
+
+enum : int
+{
+    REG_CREATED_NEW_KEY =         0x00000001,   // New Registry Key created
+    REG_OPENED_EXISTING_KEY =     0x00000002,   // Existing Key opened
+}
+
+//
+//
+// Predefined Value Types.
+//
+enum
+{
+    REG_NONE =                    0,   // No value type
+    REG_SZ =                      1,   // Unicode nul terminated string
+    REG_EXPAND_SZ =               2,   // Unicode nul terminated string
+                                            // (with environment variable references)
+    REG_BINARY =                  3,   // Free form binary
+    REG_DWORD =                   4,   // 32-bit number
+    REG_DWORD_LITTLE_ENDIAN =     4,   // 32-bit number (same as REG_DWORD)
+    REG_DWORD_BIG_ENDIAN =        5,   // 32-bit number
+    REG_LINK =                    6,   // Symbolic Link (unicode)
+    REG_MULTI_SZ =                7,   // Multiple Unicode strings
+    REG_RESOURCE_LIST =           8,   // Resource list in the resource map
+    REG_FULL_RESOURCE_DESCRIPTOR = 9,  // Resource list in the hardware description
+    REG_RESOURCE_REQUIREMENTS_LIST = 10,
+    REG_QWORD =         11,
+    REG_QWORD_LITTLE_ENDIAN =   11,
+}
+
+/*
+ * MessageBox() Flags
+ */
+enum
+{
+    MB_OK =                       0x00000000,
+    MB_OKCANCEL =                 0x00000001,
+    MB_ABORTRETRYIGNORE =         0x00000002,
+    MB_YESNOCANCEL =              0x00000003,
+    MB_YESNO =                    0x00000004,
+    MB_RETRYCANCEL =              0x00000005,
+
+
+    MB_ICONHAND =                 0x00000010,
+    MB_ICONQUESTION =             0x00000020,
+    MB_ICONEXCLAMATION =          0x00000030,
+    MB_ICONASTERISK =             0x00000040,
+
+
+    MB_USERICON =                 0x00000080,
+    MB_ICONWARNING =              MB_ICONEXCLAMATION,
+    MB_ICONERROR =                MB_ICONHAND,
+
+
+    MB_ICONINFORMATION =          MB_ICONASTERISK,
+    MB_ICONSTOP =                 MB_ICONHAND,
+
+    MB_DEFBUTTON1 =               0x00000000,
+    MB_DEFBUTTON2 =               0x00000100,
+    MB_DEFBUTTON3 =               0x00000200,
+
+    MB_DEFBUTTON4 =               0x00000300,
+
+
+    MB_APPLMODAL =                0x00000000,
+    MB_SYSTEMMODAL =              0x00001000,
+    MB_TASKMODAL =                0x00002000,
+
+    MB_HELP =                     0x00004000, // Help Button
+
+
+    MB_NOFOCUS =                  0x00008000,
+    MB_SETFOREGROUND =            0x00010000,
+    MB_DEFAULT_DESKTOP_ONLY =     0x00020000,
+
+
+    MB_TOPMOST =                  0x00040000,
+    MB_RIGHT =                    0x00080000,
+    MB_RTLREADING =               0x00100000,
+
+
+    MB_TYPEMASK =                 0x0000000F,
+    MB_ICONMASK =                 0x000000F0,
+    MB_DEFMASK =                  0x00000F00,
+    MB_MODEMASK =                 0x00003000,
+    MB_MISCMASK =                 0x0000C000,
+}
+
+
+int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
+int MessageBoxExA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId);
+
+
+enum : HKEY
+{
+    HKEY_CLASSES_ROOT =           cast(HKEY)(0x80000000),
+    HKEY_CURRENT_USER =           cast(HKEY)(0x80000001),
+    HKEY_LOCAL_MACHINE =          cast(HKEY)(0x80000002),
+    HKEY_USERS =                  cast(HKEY)(0x80000003),
+    HKEY_PERFORMANCE_DATA =       cast(HKEY)(0x80000004),
+    HKEY_PERFORMANCE_TEXT =       cast(HKEY)(0x80000050),
+    HKEY_PERFORMANCE_NLSTEXT =    cast(HKEY)(0x80000060),
+    HKEY_CURRENT_CONFIG =         cast(HKEY)(0x80000005),
+    HKEY_DYN_DATA =               cast(HKEY)(0x80000006),
+}
+
+
+enum
+{
+    REG_OPTION_RESERVED =         (0x00000000),   // Parameter is reserved
+
+    REG_OPTION_NON_VOLATILE =     (0x00000000),   // Key is preserved
+                                                    // when system is rebooted
+
+    REG_OPTION_VOLATILE =         (0x00000001),   // Key is not preserved
+                                                    // when system is rebooted
+
+    REG_OPTION_CREATE_LINK =      (0x00000002),   // Created key is a
+                                                    // symbolic link
+
+    REG_OPTION_BACKUP_RESTORE =   (0x00000004),   // open for backup or restore
+                                                    // special access rules
+                                                    // privilege required
+
+    REG_OPTION_OPEN_LINK =        (0x00000008),   // Open symbolic link
+
+    REG_LEGAL_OPTION = (REG_OPTION_RESERVED | REG_OPTION_NON_VOLATILE | REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK | REG_OPTION_BACKUP_RESTORE | REG_OPTION_OPEN_LINK),
+}
+
+export LONG RegDeleteKeyA(HKEY hKey, LPCSTR lpSubKey);
+export LONG RegDeleteValueA(HKEY hKey, LPCSTR lpValueName);
+
+export LONG  RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName, LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass, FILETIME* lpftLastWriteTime);
+export LONG RegEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpValueName, LPDWORD lpcbValueName, LPDWORD lpReserved,
+    LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
+
+export LONG RegCloseKey(HKEY hKey);
+export LONG RegFlushKey(HKEY hKey);
+
+export LONG RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult);
+export LONG RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);
+
+export LONG RegQueryInfoKeyA(HKEY hKey, LPSTR lpClass, LPDWORD lpcbClass,
+    LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcbMaxSubKeyLen, LPDWORD lpcbMaxClassLen,
+    LPDWORD lpcValues, LPDWORD lpcbMaxValueNameLen, LPDWORD lpcbMaxValueLen, LPDWORD lpcbSecurityDescriptor,
+    PFILETIME lpftLastWriteTime);
+
+export LONG RegQueryValueA(HKEY hKey, LPCSTR lpSubKey, LPSTR lpValue,
+    LPLONG lpcbValue);
+
+export LONG RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass,
+   DWORD dwOptions, REGSAM samDesired, SECURITY_ATTRIBUTES* lpSecurityAttributes,
+    PHKEY phkResult, LPDWORD lpdwDisposition);
+
+export LONG RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, BYTE* lpData, DWORD cbData);
+
+struct MEMORY_BASIC_INFORMATION {
+    PVOID BaseAddress;
+    PVOID AllocationBase;
+    DWORD AllocationProtect;
+    DWORD RegionSize;
+    DWORD State;
+    DWORD Protect;
+    DWORD Type;
+}
+alias MEMORY_BASIC_INFORMATION* PMEMORY_BASIC_INFORMATION;
+
+enum
+{
+    SECTION_QUERY       = 0x0001,
+    SECTION_MAP_WRITE   = 0x0002,
+    SECTION_MAP_READ    = 0x0004,
+    SECTION_MAP_EXECUTE = 0x0008,
+    SECTION_EXTEND_SIZE = 0x0010,
+
+    SECTION_ALL_ACCESS = cast(int)(STANDARD_RIGHTS_REQUIRED|SECTION_QUERY| SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE),
+    PAGE_NOACCESS          = 0x01,
+    PAGE_READONLY          = 0x02,
+    PAGE_READWRITE         = 0x04,
+    PAGE_WRITECOPY         = 0x08,
+    PAGE_EXECUTE           = 0x10,
+    PAGE_EXECUTE_READ      = 0x20,
+    PAGE_EXECUTE_READWRITE = 0x40,
+    PAGE_EXECUTE_WRITECOPY = 0x80,
+    PAGE_GUARD            = 0x100,
+    PAGE_NOCACHE          = 0x200,
+    MEM_COMMIT           = 0x1000,
+    MEM_RESERVE          = 0x2000,
+    MEM_DECOMMIT         = 0x4000,
+    MEM_RELEASE          = 0x8000,
+    MEM_FREE            = 0x10000,
+    MEM_PRIVATE         = 0x20000,
+    MEM_MAPPED          = 0x40000,
+    MEM_RESET           = 0x80000,
+    MEM_TOP_DOWN       = 0x100000,
+    SEC_FILE           = 0x800000,
+    SEC_IMAGE         = 0x1000000,
+    SEC_RESERVE       = 0x4000000,
+    SEC_COMMIT        = 0x8000000,
+    SEC_NOCACHE      = 0x10000000,
+    MEM_IMAGE        = SEC_IMAGE,
+}
+
+enum
+{
+    FILE_MAP_COPY =       SECTION_QUERY,
+    FILE_MAP_WRITE =      SECTION_MAP_WRITE,
+    FILE_MAP_READ =       SECTION_MAP_READ,
+    FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS,
+}
+
+
+//
+// Define access rights to files and directories
+//
+
+//
+// The FILE_READ_DATA and FILE_WRITE_DATA constants are also defined in
+// devioctl.h as FILE_READ_ACCESS and FILE_WRITE_ACCESS. The values for these
+// constants *MUST* always be in sync.
+// The values are redefined in devioctl.h because they must be available to
+// both DOS and NT.
+//
+
+enum
+{
+    FILE_READ_DATA =            ( 0x0001 ),   // file & pipe
+    FILE_LIST_DIRECTORY =       ( 0x0001 ),    // directory
+
+    FILE_WRITE_DATA =           ( 0x0002 ),    // file & pipe
+    FILE_ADD_FILE =             ( 0x0002 ),    // directory
+
+    FILE_APPEND_DATA =          ( 0x0004 ),    // file
+    FILE_ADD_SUBDIRECTORY =     ( 0x0004 ),    // directory
+    FILE_CREATE_PIPE_INSTANCE = ( 0x0004 ),    // named pipe
+
+    FILE_READ_EA =              ( 0x0008 ),    // file & directory
+
+    FILE_WRITE_EA =             ( 0x0010 ),    // file & directory
+
+    FILE_EXECUTE =              ( 0x0020 ),    // file
+    FILE_TRAVERSE =             ( 0x0020 ),    // directory
+
+    FILE_DELETE_CHILD =         ( 0x0040 ),    // directory
+
+    FILE_READ_ATTRIBUTES =      ( 0x0080 ),    // all
+
+    FILE_WRITE_ATTRIBUTES =     ( 0x0100 ),    // all
+
+    FILE_ALL_ACCESS =       cast(int)(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF),
+
+    FILE_GENERIC_READ =         cast(int)(STANDARD_RIGHTS_READ  | FILE_READ_DATA |  FILE_READ_ATTRIBUTES |                 FILE_READ_EA |  SYNCHRONIZE),
+
+    FILE_GENERIC_WRITE =        cast(int)(STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA |  FILE_WRITE_ATTRIBUTES |                      FILE_WRITE_EA  |  FILE_APPEND_DATA |  SYNCHRONIZE),
+
+    FILE_GENERIC_EXECUTE =      cast(int)(STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES |                 FILE_EXECUTE |  SYNCHRONIZE),
+}
+
+export
+{
+ BOOL  FreeResource(HGLOBAL hResData);
+ LPVOID LockResource(HGLOBAL hResData);
+ BOOL GlobalUnlock(HGLOBAL hMem);
+ HGLOBAL GlobalFree(HGLOBAL hMem);
+ UINT GlobalCompact(DWORD dwMinFree);
+ void GlobalFix(HGLOBAL hMem);
+ void GlobalUnfix(HGLOBAL hMem);
+ LPVOID GlobalWire(HGLOBAL hMem);
+ BOOL GlobalUnWire(HGLOBAL hMem);
+ void GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer);
+ HLOCAL LocalAlloc(UINT uFlags, UINT uBytes);
+ HLOCAL LocalReAlloc(HLOCAL hMem, UINT uBytes, UINT uFlags);
+ LPVOID LocalLock(HLOCAL hMem);
+ HLOCAL LocalHandle(LPCVOID pMem);
+ BOOL LocalUnlock(HLOCAL hMem);
+ UINT LocalSize(HLOCAL hMem);
+ UINT LocalFlags(HLOCAL hMem);
+ HLOCAL LocalFree(HLOCAL hMem);
+ UINT LocalShrink(HLOCAL hMem, UINT cbNewSize);
+ UINT LocalCompact(UINT uMinFree);
+ BOOL FlushInstructionCache(HANDLE hProcess, LPCVOID lpBaseAddress, DWORD dwSize);
+ LPVOID VirtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect);
+ BOOL VirtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType);
+ BOOL VirtualProtect(LPVOID lpAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
+ DWORD VirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, DWORD dwLength);
+ LPVOID VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect);
+ BOOL VirtualFreeEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType);
+ BOOL VirtualProtectEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
+ DWORD VirtualQueryEx(HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, DWORD dwLength);
+}
+
+struct SYSTEMTIME
+{
+    WORD wYear;
+    WORD wMonth;
+    WORD wDayOfWeek;
+    WORD wDay;
+    WORD wHour;
+    WORD wMinute;
+    WORD wSecond;
+    WORD wMilliseconds;
+}
+
+struct TIME_ZONE_INFORMATION {
+    LONG Bias;
+    WCHAR StandardName[ 32 ];
+    SYSTEMTIME StandardDate;
+    LONG StandardBias;
+    WCHAR DaylightName[ 32 ];
+    SYSTEMTIME DaylightDate;
+    LONG DaylightBias;
+}
+
+enum
+{
+    TIME_ZONE_ID_UNKNOWN =  0,
+    TIME_ZONE_ID_STANDARD = 1,
+    TIME_ZONE_ID_DAYLIGHT = 2,
+}
+
+export void GetSystemTime(SYSTEMTIME* lpSystemTime);
+export BOOL GetFileTime(HANDLE hFile, FILETIME *lpCreationTime, FILETIME *lpLastAccessTime, FILETIME *lpLastWriteTime);
+export void GetSystemTimeAsFileTime(FILETIME* lpSystemTimeAsFileTime);
+export BOOL SetSystemTime(SYSTEMTIME* lpSystemTime);
+export BOOL SetFileTime(HANDLE hFile, in FILETIME *lpCreationTime, in FILETIME *lpLastAccessTime, in FILETIME *lpLastWriteTime);
+export void GetLocalTime(SYSTEMTIME* lpSystemTime);
+export BOOL SetLocalTime(SYSTEMTIME* lpSystemTime);
+export BOOL SystemTimeToTzSpecificLocalTime(TIME_ZONE_INFORMATION* lpTimeZoneInformation, SYSTEMTIME* lpUniversalTime, SYSTEMTIME* lpLocalTime);
+export DWORD GetTimeZoneInformation(TIME_ZONE_INFORMATION* lpTimeZoneInformation);
+export BOOL SetTimeZoneInformation(TIME_ZONE_INFORMATION* lpTimeZoneInformation);
+
+export BOOL SystemTimeToFileTime(in SYSTEMTIME *lpSystemTime, FILETIME* lpFileTime);
+export BOOL FileTimeToLocalFileTime(in FILETIME *lpFileTime, FILETIME* lpLocalFileTime);
+export BOOL LocalFileTimeToFileTime(in FILETIME *lpLocalFileTime, FILETIME* lpFileTime);
+export BOOL FileTimeToSystemTime(in FILETIME *lpFileTime, SYSTEMTIME* lpSystemTime);
+export LONG CompareFileTime(in FILETIME *lpFileTime1, in FILETIME *lpFileTime2);
+export BOOL FileTimeToDosDateTime(in FILETIME *lpFileTime, WORD* lpFatDate, WORD* lpFatTime);
+export BOOL DosDateTimeToFileTime(WORD wFatDate, WORD wFatTime, FILETIME* lpFileTime);
+export DWORD GetTickCount();
+export BOOL SetSystemTimeAdjustment(DWORD dwTimeAdjustment, BOOL bTimeAdjustmentDisabled);
+export BOOL GetSystemTimeAdjustment(DWORD* lpTimeAdjustment, DWORD* lpTimeIncrement, BOOL* lpTimeAdjustmentDisabled);
+export DWORD FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, void* *Arguments);export DWORD FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, void* *Arguments);
+
+enum
+{
+    FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100,
+    FORMAT_MESSAGE_IGNORE_INSERTS =  0x00000200,
+    FORMAT_MESSAGE_FROM_STRING =     0x00000400,
+    FORMAT_MESSAGE_FROM_HMODULE =    0x00000800,
+    FORMAT_MESSAGE_FROM_SYSTEM =     0x00001000,
+    FORMAT_MESSAGE_ARGUMENT_ARRAY =  0x00002000,
+    FORMAT_MESSAGE_MAX_WIDTH_MASK =  0x000000FF,
+};
+
+
+//
+//  Language IDs.
+//
+//  The following two combinations of primary language ID and
+//  sublanguage ID have special semantics:
+//
+//    Primary Language ID   Sublanguage ID      Result
+//    -------------------   ---------------     ------------------------
+//    LANG_NEUTRAL          SUBLANG_NEUTRAL     Language neutral
+//    LANG_NEUTRAL          SUBLANG_DEFAULT     User default language
+//    LANG_NEUTRAL          SUBLANG_SYS_DEFAULT System default language
+//
+
+//
+//  Primary language IDs.
+//
+
+enum
+{
+    LANG_NEUTRAL                     = 0x00,
+
+    LANG_AFRIKAANS                   = 0x36,
+    LANG_ALBANIAN                    = 0x1c,
+    LANG_ARABIC                      = 0x01,
+    LANG_BASQUE                      = 0x2d,
+    LANG_BELARUSIAN                  = 0x23,
+    LANG_BULGARIAN                   = 0x02,
+    LANG_CATALAN                     = 0x03,
+    LANG_CHINESE                     = 0x04,
+    LANG_CROATIAN                    = 0x1a,
+    LANG_CZECH                       = 0x05,
+    LANG_DANISH                      = 0x06,
+    LANG_DUTCH                       = 0x13,
+    LANG_ENGLISH                     = 0x09,
+    LANG_ESTONIAN                    = 0x25,
+    LANG_FAEROESE                    = 0x38,
+    LANG_FARSI                       = 0x29,
+    LANG_FINNISH                     = 0x0b,
+    LANG_FRENCH                      = 0x0c,
+    LANG_GERMAN                      = 0x07,
+    LANG_GREEK                       = 0x08,
+    LANG_HEBREW                      = 0x0d,
+    LANG_HUNGARIAN                   = 0x0e,
+    LANG_ICELANDIC                   = 0x0f,
+    LANG_INDONESIAN                  = 0x21,
+    LANG_ITALIAN                     = 0x10,
+    LANG_JAPANESE                    = 0x11,
+    LANG_KOREAN                      = 0x12,
+    LANG_LATVIAN                     = 0x26,
+    LANG_LITHUANIAN                  = 0x27,
+    LANG_NORWEGIAN                   = 0x14,
+    LANG_POLISH                      = 0x15,
+    LANG_PORTUGUESE                  = 0x16,
+    LANG_ROMANIAN                    = 0x18,
+    LANG_RUSSIAN                     = 0x19,
+    LANG_SERBIAN                     = 0x1a,
+    LANG_SLOVAK                      = 0x1b,
+    LANG_SLOVENIAN                   = 0x24,
+    LANG_SPANISH                     = 0x0a,
+    LANG_SWEDISH                     = 0x1d,
+    LANG_THAI                        = 0x1e,
+    LANG_TURKISH                     = 0x1f,
+    LANG_UKRAINIAN                   = 0x22,
+    LANG_VIETNAMESE                  = 0x2a,
+}
+//
+//  Sublanguage IDs.
+//
+//  The name immediately following SUBLANG_ dictates which primary
+//  language ID that sublanguage ID can be combined with to form a
+//  valid language ID.
+//
+enum
+{
+    SUBLANG_NEUTRAL =                  0x00,    // language neutral
+    SUBLANG_DEFAULT =                  0x01,    // user default
+    SUBLANG_SYS_DEFAULT =              0x02,    // system default
+
+    SUBLANG_ARABIC_SAUDI_ARABIA =      0x01,    // Arabic (Saudi Arabia)
+    SUBLANG_ARABIC_IRAQ =              0x02,    // Arabic (Iraq)
+    SUBLANG_ARABIC_EGYPT =             0x03,    // Arabic (Egypt)
+    SUBLANG_ARABIC_LIBYA =             0x04,    // Arabic (Libya)
+    SUBLANG_ARABIC_ALGERIA =           0x05,    // Arabic (Algeria)
+    SUBLANG_ARABIC_MOROCCO =           0x06,    // Arabic (Morocco)
+    SUBLANG_ARABIC_TUNISIA =           0x07,    // Arabic (Tunisia)
+    SUBLANG_ARABIC_OMAN =              0x08,    // Arabic (Oman)
+    SUBLANG_ARABIC_YEMEN =             0x09,    // Arabic (Yemen)
+    SUBLANG_ARABIC_SYRIA =             0x0a,    // Arabic (Syria)
+    SUBLANG_ARABIC_JORDAN =            0x0b,    // Arabic (Jordan)
+    SUBLANG_ARABIC_LEBANON =           0x0c,    // Arabic (Lebanon)
+    SUBLANG_ARABIC_KUWAIT =            0x0d,    // Arabic (Kuwait)
+    SUBLANG_ARABIC_UAE =               0x0e,    // Arabic (U.A.E)
+    SUBLANG_ARABIC_BAHRAIN =           0x0f,    // Arabic (Bahrain)
+    SUBLANG_ARABIC_QATAR =             0x10,    // Arabic (Qatar)
+    SUBLANG_CHINESE_TRADITIONAL =      0x01,    // Chinese (Taiwan)
+    SUBLANG_CHINESE_SIMPLIFIED =       0x02,    // Chinese (PR China)
+    SUBLANG_CHINESE_HONGKONG =         0x03,    // Chinese (Hong Kong)
+    SUBLANG_CHINESE_SINGAPORE =        0x04,    // Chinese (Singapore)
+    SUBLANG_DUTCH =                    0x01,    // Dutch
+    SUBLANG_DUTCH_BELGIAN =            0x02,    // Dutch (Belgian)
+    SUBLANG_ENGLISH_US =               0x01,    // English (USA)
+    SUBLANG_ENGLISH_UK =               0x02,    // English (UK)
+    SUBLANG_ENGLISH_AUS =              0x03,    // English (Australian)
+    SUBLANG_ENGLISH_CAN =              0x04,    // English (Canadian)
+    SUBLANG_ENGLISH_NZ =               0x05,    // English (New Zealand)
+    SUBLANG_ENGLISH_EIRE =             0x06,    // English (Irish)
+    SUBLANG_ENGLISH_SOUTH_AFRICA =     0x07,    // English (South Africa)
+    SUBLANG_ENGLISH_JAMAICA =          0x08,    // English (Jamaica)
+    SUBLANG_ENGLISH_CARIBBEAN =        0x09,    // English (Caribbean)
+    SUBLANG_ENGLISH_BELIZE =           0x0a,    // English (Belize)
+    SUBLANG_ENGLISH_TRINIDAD =         0x0b,    // English (Trinidad)
+    SUBLANG_FRENCH =                   0x01,    // French
+    SUBLANG_FRENCH_BELGIAN =           0x02,    // French (Belgian)
+    SUBLANG_FRENCH_CANADIAN =          0x03,    // French (Canadian)
+    SUBLANG_FRENCH_SWISS =             0x04,    // French (Swiss)
+    SUBLANG_FRENCH_LUXEMBOURG =        0x05,    // French (Luxembourg)
+    SUBLANG_GERMAN =                   0x01,    // German
+    SUBLANG_GERMAN_SWISS =             0x02,    // German (Swiss)
+    SUBLANG_GERMAN_AUSTRIAN =          0x03,    // German (Austrian)
+    SUBLANG_GERMAN_LUXEMBOURG =        0x04,    // German (Luxembourg)
+    SUBLANG_GERMAN_LIECHTENSTEIN =     0x05,    // German (Liechtenstein)
+    SUBLANG_ITALIAN =                  0x01,    // Italian
+    SUBLANG_ITALIAN_SWISS =            0x02,    // Italian (Swiss)
+    SUBLANG_KOREAN =                   0x01,    // Korean (Extended Wansung)
+    SUBLANG_KOREAN_JOHAB =             0x02,    // Korean (Johab)
+    SUBLANG_NORWEGIAN_BOKMAL =         0x01,    // Norwegian (Bokmal)
+    SUBLANG_NORWEGIAN_NYNORSK =        0x02,    // Norwegian (Nynorsk)
+    SUBLANG_PORTUGUESE =               0x02,    // Portuguese
+    SUBLANG_PORTUGUESE_BRAZILIAN =     0x01,    // Portuguese (Brazilian)
+    SUBLANG_SERBIAN_LATIN =            0x02,    // Serbian (Latin)
+    SUBLANG_SERBIAN_CYRILLIC =         0x03,    // Serbian (Cyrillic)
+    SUBLANG_SPANISH =                  0x01,    // Spanish (Castilian)
+    SUBLANG_SPANISH_MEXICAN =          0x02,    // Spanish (Mexican)
+    SUBLANG_SPANISH_MODERN =           0x03,    // Spanish (Modern)
+    SUBLANG_SPANISH_GUATEMALA =        0x04,    // Spanish (Guatemala)
+    SUBLANG_SPANISH_COSTA_RICA =       0x05,    // Spanish (Costa Rica)
+    SUBLANG_SPANISH_PANAMA =           0x06,    // Spanish (Panama)
+    SUBLANG_SPANISH_DOMINICAN_REPUBLIC = 0x07,  // Spanish (Dominican Republic)
+    SUBLANG_SPANISH_VENEZUELA =        0x08,    // Spanish (Venezuela)
+    SUBLANG_SPANISH_COLOMBIA =         0x09,    // Spanish (Colombia)
+    SUBLANG_SPANISH_PERU =             0x0a,    // Spanish (Peru)
+    SUBLANG_SPANISH_ARGENTINA =        0x0b,    // Spanish (Argentina)
+    SUBLANG_SPANISH_ECUADOR =          0x0c,    // Spanish (Ecuador)
+    SUBLANG_SPANISH_CHILE =            0x0d,    // Spanish (Chile)
+    SUBLANG_SPANISH_URUGUAY =          0x0e,    // Spanish (Uruguay)
+    SUBLANG_SPANISH_PARAGUAY =         0x0f,    // Spanish (Paraguay)
+    SUBLANG_SPANISH_BOLIVIA =          0x10,    // Spanish (Bolivia)
+    SUBLANG_SPANISH_EL_SALVADOR =      0x11,    // Spanish (El Salvador)
+    SUBLANG_SPANISH_HONDURAS =         0x12,    // Spanish (Honduras)
+    SUBLANG_SPANISH_NICARAGUA =        0x13,    // Spanish (Nicaragua)
+    SUBLANG_SPANISH_PUERTO_RICO =      0x14,    // Spanish (Puerto Rico)
+    SUBLANG_SWEDISH =                  0x01,    // Swedish
+    SUBLANG_SWEDISH_FINLAND =          0x02,    // Swedish (Finland)
+}
+//
+//  Sorting IDs.
+//
+
+enum
+{
+    SORT_DEFAULT                   = 0x0,    // sorting default
+
+    SORT_JAPANESE_XJIS             = 0x0,    // Japanese XJIS order
+    SORT_JAPANESE_UNICODE          = 0x1,    // Japanese Unicode order
+
+    SORT_CHINESE_BIG5              = 0x0,    // Chinese BIG5 order
+    SORT_CHINESE_PRCP              = 0x0,    // PRC Chinese Phonetic order
+    SORT_CHINESE_UNICODE           = 0x1,    // Chinese Unicode order
+    SORT_CHINESE_PRC               = 0x2,    // PRC Chinese Stroke Count order
+
+    SORT_KOREAN_KSC                = 0x0,    // Korean KSC order
+    SORT_KOREAN_UNICODE            = 0x1,    // Korean Unicode order
+
+    SORT_GERMAN_PHONE_BOOK         = 0x1,    // German Phone Book order
+}
+
+// end_r_winnt
+
+//
+//  A language ID is a 16 bit value which is the combination of a
+//  primary language ID and a secondary language ID.  The bits are
+//  allocated as follows:
+//
+//       +-----------------------+-------------------------+
+//       |     Sublanguage ID    |   Primary Language ID   |
+//       +-----------------------+-------------------------+
+//        15                   10 9                       0   bit
+//
+//
+//  Language ID creation/extraction macros:
+//
+//    MAKELANGID    - construct language id from a primary language id and
+//                    a sublanguage id.
+//    PRIMARYLANGID - extract primary language id from a language id.
+//    SUBLANGID     - extract sublanguage id from a language id.
+//
+
+int MAKELANGID(int p, int s) { return ((cast(WORD)s) << 10) | cast(WORD)p; }
+WORD PRIMARYLANGID(int lgid) { return cast(WORD)(lgid & 0x3ff); }
+WORD SUBLANGID(int lgid)     { return cast(WORD)(lgid >> 10); }
+
+
+struct FLOATING_SAVE_AREA {
+    DWORD   ControlWord;
+    DWORD   StatusWord;
+    DWORD   TagWord;
+    DWORD   ErrorOffset;
+    DWORD   ErrorSelector;
+    DWORD   DataOffset;
+    DWORD   DataSelector;
+    BYTE    RegisterArea[80 ];
+    DWORD   Cr0NpxState;
+}
+
+enum
+{
+    SIZE_OF_80387_REGISTERS =      80,
+//
+// The following flags control the contents of the CONTEXT structure.
+//
+    CONTEXT_i386 =    0x00010000,    // this assumes that i386 and
+    CONTEXT_i486 =    0x00010000,    // i486 have identical context records
+
+    CONTEXT_CONTROL =         (CONTEXT_i386 | 0x00000001), // SS:SP, CS:IP, FLAGS, BP
+    CONTEXT_INTEGER =         (CONTEXT_i386 | 0x00000002), // AX, BX, CX, DX, SI, DI
+    CONTEXT_SEGMENTS =        (CONTEXT_i386 | 0x00000004), // DS, ES, FS, GS
+    CONTEXT_FLOATING_POINT =  (CONTEXT_i386 | 0x00000008), // 387 state
+    CONTEXT_DEBUG_REGISTERS = (CONTEXT_i386 | 0x00000010), // DB 0-3,6,7
+
+    CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS),
+}
+
+struct CONTEXT
+{
+
+    //
+    // The flags values within this flag control the contents of
+    // a CONTEXT record.
+    //
+    // If the context record is used as an input parameter, then
+    // for each portion of the context record controlled by a flag
+    // whose value is set, it is assumed that that portion of the
+    // context record contains valid context. If the context record
+    // is being used to modify a threads context, then only that
+    // portion of the threads context will be modified.
+    //
+    // If the context record is used as an IN OUT parameter to capture
+    // the context of a thread, then only those portions of the thread's
+    // context corresponding to set flags will be returned.
+    //
+    // The context record is never used as an OUT only parameter.
+    //
+
+    DWORD ContextFlags;
+
+    //
+    // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
+    // set in ContextFlags.  Note that CONTEXT_DEBUG_REGISTERS is NOT
+    // included in CONTEXT_FULL.
+    //
+
+    DWORD   Dr0;
+    DWORD   Dr1;
+    DWORD   Dr2;
+    DWORD   Dr3;
+    DWORD   Dr6;
+    DWORD   Dr7;
+
+    //
+    // This section is specified/returned if the
+    // ContextFlags word contians the flag CONTEXT_FLOATING_POINT.
+    //
+
+    FLOATING_SAVE_AREA FloatSave;
+
+    //
+    // This section is specified/returned if the
+    // ContextFlags word contians the flag CONTEXT_SEGMENTS.
+    //
+
+    DWORD   SegGs;
+    DWORD   SegFs;
+    DWORD   SegEs;
+    DWORD   SegDs;
+
+    //
+    // This section is specified/returned if the
+    // ContextFlags word contians the flag CONTEXT_INTEGER.
+    //
+
+    DWORD   Edi;
+    DWORD   Esi;
+    DWORD   Ebx;
+    DWORD   Edx;
+    DWORD   Ecx;
+    DWORD   Eax;
+
+    //
+    // This section is specified/returned if the
+    // ContextFlags word contians the flag CONTEXT_CONTROL.
+    //
+
+    DWORD   Ebp;
+    DWORD   Eip;
+    DWORD   SegCs;              // MUST BE SANITIZED
+    DWORD   EFlags;             // MUST BE SANITIZED
+    DWORD   Esp;
+    DWORD   SegSs;
+}
+
+enum
+{
+    THREAD_BASE_PRIORITY_LOWRT =  15,  // value that gets a thread to LowRealtime-1
+    THREAD_BASE_PRIORITY_MAX =    2,   // maximum thread base priority boost
+    THREAD_BASE_PRIORITY_MIN =    -2,  // minimum thread base priority boost
+    THREAD_BASE_PRIORITY_IDLE =   -15, // value that gets a thread to idle
+
+    THREAD_PRIORITY_LOWEST =          THREAD_BASE_PRIORITY_MIN,
+    THREAD_PRIORITY_BELOW_NORMAL =    (THREAD_PRIORITY_LOWEST+1),
+    THREAD_PRIORITY_NORMAL =          0,
+    THREAD_PRIORITY_HIGHEST =         THREAD_BASE_PRIORITY_MAX,
+    THREAD_PRIORITY_ABOVE_NORMAL =    (THREAD_PRIORITY_HIGHEST-1),
+    THREAD_PRIORITY_ERROR_RETURN =    int.max,
+
+    THREAD_PRIORITY_TIME_CRITICAL =   THREAD_BASE_PRIORITY_LOWRT,
+    THREAD_PRIORITY_IDLE =            THREAD_BASE_PRIORITY_IDLE,
+}
+
+export HANDLE GetCurrentThread();
+export BOOL GetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime);
+export HANDLE GetCurrentProcess();
+export DWORD GetCurrentProcessId();
+export BOOL DuplicateHandle (HANDLE sourceProcess, HANDLE sourceThread,
+        HANDLE targetProcessHandle, HANDLE *targetHandle, DWORD access,
+        BOOL inheritHandle, DWORD options);
+export DWORD GetCurrentThreadId();
+export BOOL SetThreadPriority(HANDLE hThread, int nPriority);
+export BOOL SetThreadPriorityBoost(HANDLE hThread, BOOL bDisablePriorityBoost);
+export BOOL GetThreadPriorityBoost(HANDLE hThread, PBOOL pDisablePriorityBoost);
+export BOOL GetThreadTimes(HANDLE hThread, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime);
+export int GetThreadPriority(HANDLE hThread);
+export BOOL GetThreadContext(HANDLE hThread, CONTEXT* lpContext);
+export BOOL SetThreadContext(HANDLE hThread, CONTEXT* lpContext);
+export DWORD SuspendThread(HANDLE hThread);
+export DWORD ResumeThread(HANDLE hThread);
+export DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
+export DWORD WaitForMultipleObjects(DWORD nCount, HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds);
+export void Sleep(DWORD dwMilliseconds);
+
+// Synchronization
+
+export
+{
+LONG  InterlockedIncrement(LPLONG lpAddend);
+LONG  InterlockedDecrement(LPLONG lpAddend);
+LONG  InterlockedExchange(LPLONG Target, LONG Value);
+LONG  InterlockedExchangeAdd(LPLONG Addend, LONG Value);
+PVOID InterlockedCompareExchange(PVOID *Destination, PVOID Exchange, PVOID Comperand);
+
+void InitializeCriticalSection(CRITICAL_SECTION * lpCriticalSection);
+void EnterCriticalSection(CRITICAL_SECTION * lpCriticalSection);
+BOOL TryEnterCriticalSection(CRITICAL_SECTION * lpCriticalSection);
+void LeaveCriticalSection(CRITICAL_SECTION * lpCriticalSection);
+void DeleteCriticalSection(CRITICAL_SECTION * lpCriticalSection);
+
+}
+
+
+
+export BOOL QueryPerformanceCounter(long* lpPerformanceCount);
+export BOOL QueryPerformanceFrequency(long* lpFrequency);
+
+enum
+{
+    WM_NOTIFY =                       0x004E,
+    WM_INPUTLANGCHANGEREQUEST =       0x0050,
+    WM_INPUTLANGCHANGE =              0x0051,
+    WM_TCARD =                        0x0052,
+    WM_HELP =                         0x0053,
+    WM_USERCHANGED =                  0x0054,
+    WM_NOTIFYFORMAT =                 0x0055,
+
+    NFR_ANSI =                             1,
+    NFR_UNICODE =                          2,
+    NF_QUERY =                             3,
+    NF_REQUERY =                           4,
+
+    WM_CONTEXTMENU =                  0x007B,
+    WM_STYLECHANGING =                0x007C,
+    WM_STYLECHANGED =                 0x007D,
+    WM_DISPLAYCHANGE =                0x007E,
+    WM_GETICON =                      0x007F,
+    WM_SETICON =                      0x0080,
+
+
+
+    WM_NCCREATE =                     0x0081,
+    WM_NCDESTROY =                    0x0082,
+    WM_NCCALCSIZE =                   0x0083,
+    WM_NCHITTEST =                    0x0084,
+    WM_NCPAINT =                      0x0085,
+    WM_NCACTIVATE =                   0x0086,
+    WM_GETDLGCODE =                   0x0087,
+
+    WM_NCMOUSEMOVE =                  0x00A0,
+    WM_NCLBUTTONDOWN =                0x00A1,
+    WM_NCLBUTTONUP =                  0x00A2,
+    WM_NCLBUTTONDBLCLK =              0x00A3,
+    WM_NCRBUTTONDOWN =                0x00A4,
+    WM_NCRBUTTONUP =                  0x00A5,
+    WM_NCRBUTTONDBLCLK =              0x00A6,
+    WM_NCMBUTTONDOWN =                0x00A7,
+    WM_NCMBUTTONUP =                  0x00A8,
+    WM_NCMBUTTONDBLCLK =              0x00A9,
+
+    WM_KEYFIRST =                     0x0100,
+    WM_KEYDOWN =                      0x0100,
+    WM_KEYUP =                        0x0101,
+    WM_CHAR =                         0x0102,
+    WM_DEADCHAR =                     0x0103,
+    WM_SYSKEYDOWN =                   0x0104,
+    WM_SYSKEYUP =                     0x0105,
+    WM_SYSCHAR =                      0x0106,
+    WM_SYSDEADCHAR =                  0x0107,
+    WM_KEYLAST =                      0x0108,
+
+
+    WM_IME_STARTCOMPOSITION =         0x010D,
+    WM_IME_ENDCOMPOSITION =           0x010E,
+    WM_IME_COMPOSITION =              0x010F,
+    WM_IME_KEYLAST =                  0x010F,
+
+
+    WM_INITDIALOG =                   0x0110,
+    WM_COMMAND =                      0x0111,
+    WM_SYSCOMMAND =                   0x0112,
+    WM_TIMER =                        0x0113,
+    WM_HSCROLL =                      0x0114,
+    WM_VSCROLL =                      0x0115,
+    WM_INITMENU =                     0x0116,
+    WM_INITMENUPOPUP =                0x0117,
+    WM_MENUSELECT =                   0x011F,
+    WM_MENUCHAR =                     0x0120,
+    WM_ENTERIDLE =                    0x0121,
+
+    WM_CTLCOLORMSGBOX =               0x0132,
+    WM_CTLCOLOREDIT =                 0x0133,
+    WM_CTLCOLORLISTBOX =              0x0134,
+    WM_CTLCOLORBTN =                  0x0135,
+    WM_CTLCOLORDLG =                  0x0136,
+    WM_CTLCOLORSCROLLBAR =            0x0137,
+    WM_CTLCOLORSTATIC =               0x0138,
+
+
+
+    WM_MOUSEFIRST =                   0x0200,
+    WM_MOUSEMOVE =                    0x0200,
+    WM_LBUTTONDOWN =                  0x0201,
+    WM_LBUTTONUP =                    0x0202,
+    WM_LBUTTONDBLCLK =                0x0203,
+    WM_RBUTTONDOWN =                  0x0204,
+    WM_RBUTTONUP =                    0x0205,
+    WM_RBUTTONDBLCLK =                0x0206,
+    WM_MBUTTONDOWN =                  0x0207,
+    WM_MBUTTONUP =                    0x0208,
+    WM_MBUTTONDBLCLK =                0x0209,
+
+
+
+    WM_MOUSELAST =                    0x0209,
+
+
+
+
+
+
+
+
+    WM_PARENTNOTIFY =                 0x0210,
+    MENULOOP_WINDOW =                 0,
+    MENULOOP_POPUP =                  1,
+    WM_ENTERMENULOOP =                0x0211,
+    WM_EXITMENULOOP =                 0x0212,
+
+
+    WM_NEXTMENU =                     0x0213,
+}
+
+enum
+{
+/*
+ * Dialog Box Command IDs
+ */
+    IDOK =                1,
+    IDCANCEL =            2,
+    IDABORT =             3,
+    IDRETRY =             4,
+    IDIGNORE =            5,
+    IDYES =               6,
+    IDNO =                7,
+
+    IDCLOSE =         8,
+    IDHELP =          9,
+
+
+// end_r_winuser
+
+
+
+/*
+ * Control Manager Structures and Definitions
+ */
+
+
+
+// begin_r_winuser
+
+/*
+ * Edit Control Styles
+ */
+    ES_LEFT =             0x0000,
+    ES_CENTER =           0x0001,
+    ES_RIGHT =            0x0002,
+    ES_MULTILINE =        0x0004,
+    ES_UPPERCASE =        0x0008,
+    ES_LOWERCASE =        0x0010,
+    ES_PASSWORD =         0x0020,
+    ES_AUTOVSCROLL =      0x0040,
+    ES_AUTOHSCROLL =      0x0080,
+    ES_NOHIDESEL =        0x0100,
+    ES_OEMCONVERT =       0x0400,
+    ES_READONLY =         0x0800,
+    ES_WANTRETURN =       0x1000,
+
+    ES_NUMBER =           0x2000,
+
+
+// end_r_winuser
+
+
+
+/*
+ * Edit Control Notification Codes
+ */
+    EN_SETFOCUS =         0x0100,
+    EN_KILLFOCUS =        0x0200,
+    EN_CHANGE =           0x0300,
+    EN_UPDATE =           0x0400,
+    EN_ERRSPACE =         0x0500,
+    EN_MAXTEXT =          0x0501,
+    EN_HSCROLL =          0x0601,
+    EN_VSCROLL =          0x0602,
+
+
+/* Edit control EM_SETMARGIN parameters */
+    EC_LEFTMARGIN =       0x0001,
+    EC_RIGHTMARGIN =      0x0002,
+    EC_USEFONTINFO =      0xffff,
+
+
+
+
+// begin_r_winuser
+
+/*
+ * Edit Control Messages
+ */
+    EM_GETSEL =               0x00B0,
+    EM_SETSEL =               0x00B1,
+    EM_GETRECT =              0x00B2,
+    EM_SETRECT =              0x00B3,
+    EM_SETRECTNP =            0x00B4,
+    EM_SCROLL =               0x00B5,
+    EM_LINESCROLL =           0x00B6,
+    EM_SCROLLCARET =          0x00B7,
+    EM_GETMODIFY =            0x00B8,
+    EM_SETMODIFY =            0x00B9,
+    EM_GETLINECOUNT =         0x00BA,
+    EM_LINEINDEX =            0x00BB,
+    EM_SETHANDLE =            0x00BC,
+    EM_GETHANDLE =            0x00BD,
+    EM_GETTHUMB =             0x00BE,
+    EM_LINELENGTH =           0x00C1,
+    EM_REPLACESEL =           0x00C2,
+    EM_GETLINE =              0x00C4,
+    EM_LIMITTEXT =            0x00C5,
+    EM_CANUNDO =              0x00C6,
+    EM_UNDO =                 0x00C7,
+    EM_FMTLINES =             0x00C8,
+    EM_LINEFROMCHAR =         0x00C9,
+    EM_SETTABSTOPS =          0x00CB,
+    EM_SETPASSWORDCHAR =      0x00CC,
+    EM_EMPTYUNDOBUFFER =      0x00CD,
+    EM_GETFIRSTVISIBLELINE =  0x00CE,
+    EM_SETREADONLY =          0x00CF,
+    EM_SETWORDBREAKPROC =     0x00D0,
+    EM_GETWORDBREAKPROC =     0x00D1,
+    EM_GETPASSWORDCHAR =      0x00D2,
+
+    EM_SETMARGINS =           0x00D3,
+    EM_GETMARGINS =           0x00D4,
+    EM_SETLIMITTEXT =         EM_LIMITTEXT, /* ;win40 Name change */
+    EM_GETLIMITTEXT =         0x00D5,
+    EM_POSFROMCHAR =          0x00D6,
+    EM_CHARFROMPOS =          0x00D7,
+
+
+
+// end_r_winuser
+
+
+/*
+ * EDITWORDBREAKPROC code values
+ */
+    WB_LEFT =            0,
+    WB_RIGHT =           1,
+    WB_ISDELIMITER =     2,
+
+// begin_r_winuser
+
+/*
+ * Button Control Styles
+ */
+    BS_PUSHBUTTON =       0x00000000,
+    BS_DEFPUSHBUTTON =    0x00000001,
+    BS_CHECKBOX =         0x00000002,
+    BS_AUTOCHECKBOX =     0x00000003,
+    BS_RADIOBUTTON =      0x00000004,
+    BS_3STATE =           0x00000005,
+    BS_AUTO3STATE =       0x00000006,
+    BS_GROUPBOX =         0x00000007,
+    BS_USERBUTTON =       0x00000008,
+    BS_AUTORADIOBUTTON =  0x00000009,
+    BS_OWNERDRAW =        0x0000000B,
+    BS_LEFTTEXT =         0x00000020,
+
+    BS_TEXT =             0x00000000,
+    BS_ICON =             0x00000040,
+    BS_BITMAP =           0x00000080,
+    BS_LEFT =             0x00000100,
+    BS_RIGHT =            0x00000200,
+    BS_CENTER =           0x00000300,
+    BS_TOP =              0x00000400,
+    BS_BOTTOM =           0x00000800,
+    BS_VCENTER =          0x00000C00,
+    BS_PUSHLIKE =         0x00001000,
+    BS_MULTILINE =        0x00002000,
+    BS_NOTIFY =           0x00004000,
+    BS_FLAT =             0x00008000,
+    BS_RIGHTBUTTON =      BS_LEFTTEXT,
+
+
+
+/*
+ * User Button Notification Codes
+ */
+    BN_CLICKED =          0,
+    BN_PAINT =            1,
+    BN_HILITE =           2,
+    BN_UNHILITE =         3,
+    BN_DISABLE =          4,
+    BN_DOUBLECLICKED =    5,
+
+    BN_PUSHED =           BN_HILITE,
+    BN_UNPUSHED =         BN_UNHILITE,
+    BN_DBLCLK =           BN_DOUBLECLICKED,
+    BN_SETFOCUS =         6,
+    BN_KILLFOCUS =        7,
+
+/*
+ * Button Control Messages
+ */
+    BM_GETCHECK =        0x00F0,
+    BM_SETCHECK =        0x00F1,
+    BM_GETSTATE =        0x00F2,
+    BM_SETSTATE =        0x00F3,
+    BM_SETSTYLE =        0x00F4,
+
+    BM_CLICK =           0x00F5,
+    BM_GETIMAGE =        0x00F6,
+    BM_SETIMAGE =        0x00F7,
+
+    BST_UNCHECKED =      0x0000,
+    BST_CHECKED =        0x0001,
+    BST_INDETERMINATE =  0x0002,
+    BST_PUSHED =         0x0004,
+    BST_FOCUS =          0x0008,
+
+
+/*
+ * Static Control Constants
+ */
+    SS_LEFT =             0x00000000,
+    SS_CENTER =           0x00000001,
+    SS_RIGHT =            0x00000002,
+    SS_ICON =             0x00000003,
+    SS_BLACKRECT =        0x00000004,
+    SS_GRAYRECT =         0x00000005,
+    SS_WHITERECT =        0x00000006,
+    SS_BLACKFRAME =       0x00000007,
+    SS_GRAYFRAME =        0x00000008,
+    SS_WHITEFRAME =       0x00000009,
+    SS_USERITEM =         0x0000000A,
+    SS_SIMPLE =           0x0000000B,
+    SS_LEFTNOWORDWRAP =   0x0000000C,
+
+    SS_OWNERDRAW =        0x0000000D,
+    SS_BITMAP =           0x0000000E,
+    SS_ENHMETAFILE =      0x0000000F,
+    SS_ETCHEDHORZ =       0x00000010,
+    SS_ETCHEDVERT =       0x00000011,
+    SS_ETCHEDFRAME =      0x00000012,
+    SS_TYPEMASK =         0x0000001F,
+
+    SS_NOPREFIX =         0x00000080, /* Don't do "&" character translation */
+
+    SS_NOTIFY =           0x00000100,
+    SS_CENTERIMAGE =      0x00000200,
+    SS_RIGHTJUST =        0x00000400,
+    SS_REALSIZEIMAGE =    0x00000800,
+    SS_SUNKEN =           0x00001000,
+    SS_ENDELLIPSIS =      0x00004000,
+    SS_PATHELLIPSIS =     0x00008000,
+    SS_WORDELLIPSIS =     0x0000C000,
+    SS_ELLIPSISMASK =     0x0000C000,
+
+
+// end_r_winuser
+
+
+/*
+ * Static Control Mesages
+ */
+    STM_SETICON =         0x0170,
+    STM_GETICON =         0x0171,
+
+    STM_SETIMAGE =        0x0172,
+    STM_GETIMAGE =        0x0173,
+    STN_CLICKED =         0,
+    STN_DBLCLK =          1,
+    STN_ENABLE =          2,
+    STN_DISABLE =         3,
+
+    STM_MSGMAX =          0x0174,
+}
+
+
+enum
+{
+/*
+ * Window Messages
+ */
+
+    WM_NULL =                         0x0000,
+    WM_CREATE =                       0x0001,
+    WM_DESTROY =                      0x0002,
+    WM_MOVE =                         0x0003,
+    WM_SIZE =                         0x0005,
+
+    WM_ACTIVATE =                     0x0006,
+/*
+ * WM_ACTIVATE state values
+ */
+    WA_INACTIVE =     0,
+    WA_ACTIVE =       1,
+    WA_CLICKACTIVE =  2,
+
+    WM_SETFOCUS =                     0x0007,
+    WM_KILLFOCUS =                    0x0008,
+    WM_ENABLE =                       0x000A,
+    WM_SETREDRAW =                    0x000B,
+    WM_SETTEXT =                      0x000C,
+    WM_GETTEXT =                      0x000D,
+    WM_GETTEXTLENGTH =                0x000E,
+    WM_PAINT =                        0x000F,
+    WM_CLOSE =                        0x0010,
+    WM_QUERYENDSESSION =              0x0011,
+    WM_QUIT =                         0x0012,
+    WM_QUERYOPEN =                    0x0013,
+    WM_ERASEBKGND =                   0x0014,
+    WM_SYSCOLORCHANGE =               0x0015,
+    WM_ENDSESSION =                   0x0016,
+    WM_SHOWWINDOW =                   0x0018,
+    WM_WININICHANGE =                 0x001A,
+
+    WM_SETTINGCHANGE =                WM_WININICHANGE,
+
+
+
+    WM_DEVMODECHANGE =                0x001B,
+    WM_ACTIVATEAPP =                  0x001C,
+    WM_FONTCHANGE =                   0x001D,
+    WM_TIMECHANGE =                   0x001E,
+    WM_CANCELMODE =                   0x001F,
+    WM_SETCURSOR =                    0x0020,
+    WM_MOUSEACTIVATE =                0x0021,
+    WM_CHILDACTIVATE =                0x0022,
+    WM_QUEUESYNC =                    0x0023,
+
+    WM_GETMINMAXINFO =                0x0024,
+}
+
+struct RECT
+{
+    LONG    left;
+    LONG    top;
+    LONG    right;
+    LONG    bottom;
+}
+alias RECT* PRECT, NPRECT, LPRECT;
+
+struct PAINTSTRUCT {
+    HDC         hdc;
+    BOOL        fErase;
+    RECT        rcPaint;
+    BOOL        fRestore;
+    BOOL        fIncUpdate;
+    BYTE        rgbReserved[32];
+}
+alias PAINTSTRUCT* PPAINTSTRUCT, NPPAINTSTRUCT, LPPAINTSTRUCT;
+
+// flags for GetDCEx()
+
+enum
+{
+    DCX_WINDOW =           0x00000001,
+    DCX_CACHE =            0x00000002,
+    DCX_NORESETATTRS =     0x00000004,
+    DCX_CLIPCHILDREN =     0x00000008,
+    DCX_CLIPSIBLINGS =     0x00000010,
+    DCX_PARENTCLIP =       0x00000020,
+    DCX_EXCLUDERGN =       0x00000040,
+    DCX_INTERSECTRGN =     0x00000080,
+    DCX_EXCLUDEUPDATE =    0x00000100,
+    DCX_INTERSECTUPDATE =  0x00000200,
+    DCX_LOCKWINDOWUPDATE = 0x00000400,
+    DCX_VALIDATE =         0x00200000,
+}
+
+export
+{
+ BOOL UpdateWindow(HWND hWnd);
+ HWND SetActiveWindow(HWND hWnd);
+ HWND GetForegroundWindow();
+ BOOL PaintDesktop(HDC hdc);
+ BOOL SetForegroundWindow(HWND hWnd);
+ HWND WindowFromDC(HDC hDC);
+ HDC GetDC(HWND hWnd);
+ HDC GetDCEx(HWND hWnd, HRGN hrgnClip, DWORD flags);
+ HDC GetWindowDC(HWND hWnd);
+ int ReleaseDC(HWND hWnd, HDC hDC);
+ HDC BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
+ BOOL EndPaint(HWND hWnd, PAINTSTRUCT *lpPaint);
+ BOOL GetUpdateRect(HWND hWnd, LPRECT lpRect, BOOL bErase);
+ int GetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase);
+ int SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw);
+ int GetWindowRgn(HWND hWnd, HRGN hRgn);
+ int ExcludeUpdateRgn(HDC hDC, HWND hWnd);
+ BOOL InvalidateRect(HWND hWnd, RECT *lpRect, BOOL bErase);
+ BOOL ValidateRect(HWND hWnd, RECT *lpRect);
+ BOOL InvalidateRgn(HWND hWnd, HRGN hRgn, BOOL bErase);
+ BOOL ValidateRgn(HWND hWnd, HRGN hRgn);
+ BOOL RedrawWindow(HWND hWnd, RECT *lprcUpdate, HRGN hrgnUpdate, UINT flags);
+}
+
+// flags for RedrawWindow()
+enum
+{
+    RDW_INVALIDATE =          0x0001,
+    RDW_INTERNALPAINT =       0x0002,
+    RDW_ERASE =               0x0004,
+    RDW_VALIDATE =            0x0008,
+    RDW_NOINTERNALPAINT =     0x0010,
+    RDW_NOERASE =             0x0020,
+    RDW_NOCHILDREN =          0x0040,
+    RDW_ALLCHILDREN =         0x0080,
+    RDW_UPDATENOW =           0x0100,
+    RDW_ERASENOW =            0x0200,
+    RDW_FRAME =               0x0400,
+    RDW_NOFRAME =             0x0800,
+}
+
+export
+{
+ BOOL GetClientRect(HWND hWnd, LPRECT lpRect);
+ BOOL GetWindowRect(HWND hWnd, LPRECT lpRect);
+ BOOL AdjustWindowRect(LPRECT lpRect, DWORD dwStyle, BOOL bMenu);
+ BOOL AdjustWindowRectEx(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle);
+ HFONT CreateFontA(int, int, int, int, int, DWORD,
+                             DWORD, DWORD, DWORD, DWORD, DWORD,
+                             DWORD, DWORD, LPCSTR);
+ HFONT CreateFontW(int, int, int, int, int, DWORD,
+                             DWORD, DWORD, DWORD, DWORD, DWORD,
+                             DWORD, DWORD, LPCWSTR);
+}
+
+enum
+{
+    OUT_DEFAULT_PRECIS =          0,
+    OUT_STRING_PRECIS =           1,
+    OUT_CHARACTER_PRECIS =        2,
+    OUT_STROKE_PRECIS =           3,
+    OUT_TT_PRECIS =               4,
+    OUT_DEVICE_PRECIS =           5,
+    OUT_RASTER_PRECIS =           6,
+    OUT_TT_ONLY_PRECIS =          7,
+    OUT_OUTLINE_PRECIS =          8,
+    OUT_SCREEN_OUTLINE_PRECIS =   9,
+
+    CLIP_DEFAULT_PRECIS =     0,
+    CLIP_CHARACTER_PRECIS =   1,
+    CLIP_STROKE_PRECIS =      2,
+    CLIP_MASK =               0xf,
+    CLIP_LH_ANGLES =          (1<<4),
+    CLIP_TT_ALWAYS =          (2<<4),
+    CLIP_EMBEDDED =           (8<<4),
+
+    DEFAULT_QUALITY =         0,
+    DRAFT_QUALITY =           1,
+    PROOF_QUALITY =           2,
+
+    NONANTIALIASED_QUALITY =  3,
+    ANTIALIASED_QUALITY =     4,
+
+
+    DEFAULT_PITCH =           0,
+    FIXED_PITCH =             1,
+    VARIABLE_PITCH =          2,
+
+    MONO_FONT =               8,
+
+
+    ANSI_CHARSET =            0,
+    DEFAULT_CHARSET =         1,
+    SYMBOL_CHARSET =          2,
+    SHIFTJIS_CHARSET =        128,
+    HANGEUL_CHARSET =         129,
+    GB2312_CHARSET =          134,
+    CHINESEBIG5_CHARSET =     136,
+    OEM_CHARSET =             255,
+
+    JOHAB_CHARSET =           130,
+    HEBREW_CHARSET =          177,
+    ARABIC_CHARSET =          178,
+    GREEK_CHARSET =           161,
+    TURKISH_CHARSET =         162,
+    VIETNAMESE_CHARSET =      163,
+    THAI_CHARSET =            222,
+    EASTEUROPE_CHARSET =      238,
+    RUSSIAN_CHARSET =         204,
+
+    MAC_CHARSET =             77,
+    BALTIC_CHARSET =          186,
+
+    FS_LATIN1 =               0x00000001L,
+    FS_LATIN2 =               0x00000002L,
+    FS_CYRILLIC =             0x00000004L,
+    FS_GREEK =                0x00000008L,
+    FS_TURKISH =              0x00000010L,
+    FS_HEBREW =               0x00000020L,
+    FS_ARABIC =               0x00000040L,
+    FS_BALTIC =               0x00000080L,
+    FS_VIETNAMESE =           0x00000100L,
+    FS_THAI =                 0x00010000L,
+    FS_JISJAPAN =             0x00020000L,
+    FS_CHINESESIMP =          0x00040000L,
+    FS_WANSUNG =              0x00080000L,
+    FS_CHINESETRAD =          0x00100000L,
+    FS_JOHAB =                0x00200000L,
+    FS_SYMBOL =               cast(int)0x80000000L,
+
+
+/* Font Families */
+    FF_DONTCARE =         (0<<4), /* Don't care or don't know. */
+    FF_ROMAN =            (1<<4), /* Variable stroke width, serifed. */
+                                    /* Times Roman, Century Schoolbook, etc. */
+    FF_SWISS =            (2<<4), /* Variable stroke width, sans-serifed. */
+                                    /* Helvetica, Swiss, etc. */
+    FF_MODERN =           (3<<4), /* Constant stroke width, serifed or sans-serifed. */
+                                    /* Pica, Elite, Courier, etc. */
+    FF_SCRIPT =           (4<<4), /* Cursive, etc. */
+    FF_DECORATIVE =       (5<<4), /* Old English, etc. */
+
+/* Font Weights */
+    FW_DONTCARE =         0,
+    FW_THIN =             100,
+    FW_EXTRALIGHT =       200,
+    FW_LIGHT =            300,
+    FW_NORMAL =           400,
+    FW_MEDIUM =           500,
+    FW_SEMIBOLD =         600,
+    FW_BOLD =             700,
+    FW_EXTRABOLD =        800,
+    FW_HEAVY =            900,
+
+    FW_ULTRALIGHT =       FW_EXTRALIGHT,
+    FW_REGULAR =          FW_NORMAL,
+    FW_DEMIBOLD =         FW_SEMIBOLD,
+    FW_ULTRABOLD =        FW_EXTRABOLD,
+    FW_BLACK =            FW_HEAVY,
+
+    PANOSE_COUNT =               10,
+    PAN_FAMILYTYPE_INDEX =        0,
+    PAN_SERIFSTYLE_INDEX =        1,
+    PAN_WEIGHT_INDEX =            2,
+    PAN_PROPORTION_INDEX =        3,
+    PAN_CONTRAST_INDEX =          4,
+    PAN_STROKEVARIATION_INDEX =   5,
+    PAN_ARMSTYLE_INDEX =          6,
+    PAN_LETTERFORM_INDEX =        7,
+    PAN_MIDLINE_INDEX =           8,
+    PAN_XHEIGHT_INDEX =           9,
+
+    PAN_CULTURE_LATIN =           0,
+}
+
+struct RGBQUAD {
+        BYTE    rgbBlue;
+        BYTE    rgbGreen;
+        BYTE    rgbRed;
+        BYTE    rgbReserved;
+}
+alias RGBQUAD* LPRGBQUAD;
+
+struct BITMAPINFOHEADER
+{
+        DWORD      biSize;
+        LONG       biWidth;
+        LONG       biHeight;
+        WORD       biPlanes;
+        WORD       biBitCount;
+        DWORD      biCompression;
+        DWORD      biSizeImage;
+        LONG       biXPelsPerMeter;
+        LONG       biYPelsPerMeter;
+        DWORD      biClrUsed;
+        DWORD      biClrImportant;
+}
+alias BITMAPINFOHEADER* LPBITMAPINFOHEADER, PBITMAPINFOHEADER;
+
+struct BITMAPINFO {
+    BITMAPINFOHEADER    bmiHeader;
+    RGBQUAD             bmiColors[1];
+}
+alias BITMAPINFO* LPBITMAPINFO, PBITMAPINFO;
+
+struct PALETTEENTRY {
+    BYTE        peRed;
+    BYTE        peGreen;
+    BYTE        peBlue;
+    BYTE        peFlags;
+}
+alias PALETTEENTRY* PPALETTEENTRY, LPPALETTEENTRY;
+
+struct LOGPALETTE {
+    WORD        palVersion;
+    WORD        palNumEntries;
+    PALETTEENTRY        palPalEntry[1];
+}
+alias LOGPALETTE* PLOGPALETTE, NPLOGPALETTE, LPLOGPALETTE;
+
+/* Pixel format descriptor */
+struct PIXELFORMATDESCRIPTOR
+{
+    WORD  nSize;
+    WORD  nVersion;
+    DWORD dwFlags;
+    BYTE  iPixelType;
+    BYTE  cColorBits;
+    BYTE  cRedBits;
+    BYTE  cRedShift;
+    BYTE  cGreenBits;
+    BYTE  cGreenShift;
+    BYTE  cBlueBits;
+    BYTE  cBlueShift;
+    BYTE  cAlphaBits;
+    BYTE  cAlphaShift;
+    BYTE  cAccumBits;
+    BYTE  cAccumRedBits;
+    BYTE  cAccumGreenBits;
+    BYTE  cAccumBlueBits;
+    BYTE  cAccumAlphaBits;
+    BYTE  cDepthBits;
+    BYTE  cStencilBits;
+    BYTE  cAuxBuffers;
+    BYTE  iLayerType;
+    BYTE  bReserved;
+    DWORD dwLayerMask;
+    DWORD dwVisibleMask;
+    DWORD dwDamageMask;
+}
+alias PIXELFORMATDESCRIPTOR* PPIXELFORMATDESCRIPTOR, LPPIXELFORMATDESCRIPTOR;
+
+
+export
+{
+ BOOL   RoundRect(HDC, int, int, int, int, int, int);
+ BOOL   ResizePalette(HPALETTE, UINT);
+ int    SaveDC(HDC);
+ int    SelectClipRgn(HDC, HRGN);
+ int    ExtSelectClipRgn(HDC, HRGN, int);
+ int    SetMetaRgn(HDC);
+ HGDIOBJ   SelectObject(HDC, HGDIOBJ);
+ HPALETTE   SelectPalette(HDC, HPALETTE, BOOL);
+ COLORREF   SetBkColor(HDC, COLORREF);
+ int     SetBkMode(HDC, int);
+ LONG    SetBitmapBits(HBITMAP, DWORD, void *);
+ UINT    SetBoundsRect(HDC,   RECT *, UINT);
+ int     SetDIBits(HDC, HBITMAP, UINT, UINT, void *, BITMAPINFO *, UINT);
+ int     SetDIBitsToDevice(HDC, int, int, DWORD, DWORD, int,
+        int, UINT, UINT, void *, BITMAPINFO *, UINT);
+ DWORD   SetMapperFlags(HDC, DWORD);
+ int     SetGraphicsMode(HDC hdc, int iMode);
+ int     SetMapMode(HDC, int);
+ HMETAFILE     SetMetaFileBitsEx(UINT, BYTE *);
+ UINT    SetPaletteEntries(HPALETTE, UINT, UINT, PALETTEENTRY *);
+ COLORREF   SetPixel(HDC, int, int, COLORREF);
+ BOOL     SetPixelV(HDC, int, int, COLORREF);
+ BOOL    SetPixelFormat(HDC, int, PIXELFORMATDESCRIPTOR *);
+ int     SetPolyFillMode(HDC, int);
+ BOOL    StretchBlt(HDC, int, int, int, int, HDC, int, int, int, int, DWORD);
+ BOOL    SetRectRgn(HRGN, int, int, int, int);
+ int     StretchDIBits(HDC, int, int, int, int, int, int, int, int,
+         void *, BITMAPINFO *, UINT, DWORD);
+ int     SetROP2(HDC, int);
+ int     SetStretchBltMode(HDC, int);
+ UINT    SetSystemPaletteUse(HDC, UINT);
+ int     SetTextCharacterExtra(HDC, int);
+ COLORREF   SetTextColor(HDC, COLORREF);
+ UINT    SetTextAlign(HDC, UINT);
+ BOOL    SetTextJustification(HDC, int, int);
+ BOOL    UpdateColors(HDC);
+}
+
+/* Text Alignment Options */
+enum
+{
+    TA_NOUPDATECP =                0,
+    TA_UPDATECP =                  1,
+
+    TA_LEFT =                      0,
+    TA_RIGHT =                     2,
+    TA_CENTER =                    6,
+
+    TA_TOP =                       0,
+    TA_BOTTOM =                    8,
+    TA_BASELINE =                  24,
+
+    TA_RTLREADING =                256,
+    TA_MASK =       (TA_BASELINE+TA_CENTER+TA_UPDATECP+TA_RTLREADING),
+}
+
+struct POINT
+{
+    LONG  x;
+    LONG  y;
+}
+alias POINT* PPOINT, NPPOINT, LPPOINT;
+
+
+export
+{
+ BOOL    MoveToEx(HDC, int, int, LPPOINT);
+ BOOL    TextOutA(HDC, int, int, LPCSTR, int);
+ BOOL    TextOutW(HDC, int, int, LPCWSTR, int);
+}
+
+export void PostQuitMessage(int nExitCode);
+export LRESULT DefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+export HMODULE GetModuleHandleA(LPCSTR lpModuleName);
+
+alias LRESULT (* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
+
+struct WNDCLASSEXA {
+    UINT        cbSize;
+    /* Win 3.x */
+    UINT        style;
+    WNDPROC     lpfnWndProc;
+    int         cbClsExtra;
+    int         cbWndExtra;
+    HINSTANCE   hInstance;
+    HICON       hIcon;
+    HCURSOR     hCursor;
+    HBRUSH      hbrBackground;
+    LPCSTR      lpszMenuName;
+    LPCSTR      lpszClassName;
+    /* Win 4.0 */
+    HICON       hIconSm;
+}
+alias WNDCLASSEXA* PWNDCLASSEXA, NPWNDCLASSEXA, LPWNDCLASSEXA;
+
+
+struct WNDCLASSA {
+    UINT        style;
+    WNDPROC     lpfnWndProc;
+    int         cbClsExtra;
+    int         cbWndExtra;
+    HINSTANCE   hInstance;
+    HICON       hIcon;
+    HCURSOR     hCursor;
+    HBRUSH      hbrBackground;
+    LPCSTR      lpszMenuName;
+    LPCSTR      lpszClassName;
+}
+alias WNDCLASSA* PWNDCLASSA, NPWNDCLASSA, LPWNDCLASSA;
+alias WNDCLASSA WNDCLASS;
+
+/*
+ * Window Styles
+ */
+enum : uint
+{
+    WS_OVERLAPPED =       0x00000000,
+    WS_POPUP =            0x80000000,
+    WS_CHILD =            0x40000000,
+    WS_MINIMIZE =         0x20000000,
+    WS_VISIBLE =          0x10000000,
+    WS_DISABLED =         0x08000000,
+    WS_CLIPSIBLINGS =     0x04000000,
+    WS_CLIPCHILDREN =     0x02000000,
+    WS_MAXIMIZE =         0x01000000,
+    WS_CAPTION =          0x00C00000,  /* WS_BORDER | WS_DLGFRAME  */
+    WS_BORDER =           0x00800000,
+    WS_DLGFRAME =         0x00400000,
+    WS_VSCROLL =          0x00200000,
+    WS_HSCROLL =          0x00100000,
+    WS_SYSMENU =          0x00080000,
+    WS_THICKFRAME =       0x00040000,
+    WS_GROUP =            0x00020000,
+    WS_TABSTOP =          0x00010000,
+
+    WS_MINIMIZEBOX =      0x00020000,
+    WS_MAXIMIZEBOX =      0x00010000,
+
+    WS_TILED =            WS_OVERLAPPED,
+    WS_ICONIC =           WS_MINIMIZE,
+    WS_SIZEBOX =          WS_THICKFRAME,
+
+/*
+ * Common Window Styles
+ */
+    WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED |            WS_CAPTION |  WS_SYSMENU |  WS_THICKFRAME |            WS_MINIMIZEBOX |                 WS_MAXIMIZEBOX),
+    WS_TILEDWINDOW =      WS_OVERLAPPEDWINDOW,
+    WS_POPUPWINDOW =      (WS_POPUP |  WS_BORDER |  WS_SYSMENU),
+    WS_CHILDWINDOW =      (WS_CHILD),
+}
+
+/*
+ * Class styles
+ */
+enum
+{
+    CS_VREDRAW =          0x0001,
+    CS_HREDRAW =          0x0002,
+    CS_KEYCVTWINDOW =     0x0004,
+    CS_DBLCLKS =          0x0008,
+    CS_OWNDC =            0x0020,
+    CS_CLASSDC =          0x0040,
+    CS_PARENTDC =         0x0080,
+    CS_NOKEYCVT =         0x0100,
+    CS_NOCLOSE =          0x0200,
+    CS_SAVEBITS =         0x0800,
+    CS_BYTEALIGNCLIENT =  0x1000,
+    CS_BYTEALIGNWINDOW =  0x2000,
+    CS_GLOBALCLASS =      0x4000,
+
+
+    CS_IME =              0x00010000,
+}
+
+export
+{
+ HICON LoadIconA(HINSTANCE hInstance, LPCSTR lpIconName);
+ HICON LoadIconW(HINSTANCE hInstance, LPCWSTR lpIconName);
+ HCURSOR LoadCursorA(HINSTANCE hInstance, LPCSTR lpCursorName);
+ HCURSOR LoadCursorW(HINSTANCE hInstance, LPCWSTR lpCursorName);
+}
+
+
+enum : LPSTR
+{
+    IDI_APPLICATION =     cast(LPSTR)(32512),
+
+    IDC_ARROW =           cast(LPSTR)(32512),
+    IDC_CROSS =           cast(LPSTR)(32515),
+}
+
+
+/*
+ * Color Types
+ */
+enum
+{
+    CTLCOLOR_MSGBOX =         0,
+    CTLCOLOR_EDIT =           1,
+    CTLCOLOR_LISTBOX =        2,
+    CTLCOLOR_BTN =            3,
+    CTLCOLOR_DLG =            4,
+    CTLCOLOR_SCROLLBAR =      5,
+    CTLCOLOR_STATIC =         6,
+    CTLCOLOR_MAX =            7,
+
+    COLOR_SCROLLBAR =         0,
+    COLOR_BACKGROUND =        1,
+    COLOR_ACTIVECAPTION =     2,
+    COLOR_INACTIVECAPTION =   3,
+    COLOR_MENU =              4,
+    COLOR_WINDOW =            5,
+    COLOR_WINDOWFRAME =       6,
+    COLOR_MENUTEXT =          7,
+    COLOR_WINDOWTEXT =        8,
+    COLOR_CAPTIONTEXT =       9,
+    COLOR_ACTIVEBORDER =      10,
+    COLOR_INACTIVEBORDER =    11,
+    COLOR_APPWORKSPACE =      12,
+    COLOR_HIGHLIGHT =         13,
+    COLOR_HIGHLIGHTTEXT =     14,
+    COLOR_BTNFACE =           15,
+    COLOR_BTNSHADOW =         16,
+    COLOR_GRAYTEXT =          17,
+    COLOR_BTNTEXT =           18,
+    COLOR_INACTIVECAPTIONTEXT = 19,
+    COLOR_BTNHIGHLIGHT =      20,
+
+
+    COLOR_3DDKSHADOW =        21,
+    COLOR_3DLIGHT =           22,
+    COLOR_INFOTEXT =          23,
+    COLOR_INFOBK =            24,
+
+    COLOR_DESKTOP =           COLOR_BACKGROUND,
+    COLOR_3DFACE =            COLOR_BTNFACE,
+    COLOR_3DSHADOW =          COLOR_BTNSHADOW,
+    COLOR_3DHIGHLIGHT =       COLOR_BTNHIGHLIGHT,
+    COLOR_3DHILIGHT =         COLOR_BTNHIGHLIGHT,
+    COLOR_BTNHILIGHT =        COLOR_BTNHIGHLIGHT,
+}
+
+enum : int
+{
+    CW_USEDEFAULT = cast(int)0x80000000
+}
+
+/*
+ * Special value for CreateWindow, et al.
+ */
+enum : HWND
+{
+    HWND_DESKTOP = cast(HWND)0,
+}
+
+export ATOM RegisterClassA(WNDCLASSA *lpWndClass);
+
+export HWND CreateWindowExA(
+    DWORD dwExStyle,
+    LPCSTR lpClassName,
+    LPCSTR lpWindowName,
+    DWORD dwStyle,
+    int X,
+    int Y,
+    int nWidth,
+    int nHeight,
+    HWND hWndParent ,
+    HMENU hMenu,
+    HINSTANCE hInstance,
+    LPVOID lpParam);
+
+
+HWND CreateWindowA(
+    LPCSTR lpClassName,
+    LPCSTR lpWindowName,
+    DWORD dwStyle,
+    int X,
+    int Y,
+    int nWidth,
+    int nHeight,
+    HWND hWndParent ,
+    HMENU hMenu,
+    HINSTANCE hInstance,
+    LPVOID lpParam)
+{
+    return CreateWindowExA(0, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
+}
+
+/*
+ * Message structure
+ */
+struct MSG {
+    HWND        hwnd;
+    UINT        message;
+    WPARAM      wParam;
+    LPARAM      lParam;
+    DWORD       time;
+    POINT       pt;
+}
+alias MSG* PMSG, NPMSG, LPMSG;
+
+export
+{
+ BOOL GetMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
+ BOOL TranslateMessage(MSG *lpMsg);
+ LONG DispatchMessageA(MSG *lpMsg);
+ BOOL PeekMessageA(MSG *lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg);
+ HWND GetFocus();
+}
+
+export DWORD ExpandEnvironmentStringsA(LPCSTR lpSrc, LPSTR lpDst, DWORD nSize);
+
+export
+{
+ BOOL IsValidCodePage(UINT CodePage);
+ UINT GetACP();
+ UINT GetOEMCP();
+ //BOOL GetCPInfo(UINT CodePage, LPCPINFO lpCPInfo);
+ BOOL IsDBCSLeadByte(BYTE TestChar);
+ BOOL IsDBCSLeadByteEx(UINT CodePage, BYTE TestChar);
+ int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cchMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
+ int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cchMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);
+}
+
+export HANDLE CreateFileMappingA(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName);
+export HANDLE CreateFileMappingW(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCWSTR lpName);
+
+export BOOL GetMailslotInfo(HANDLE hMailslot, LPDWORD lpMaxMessageSize, LPDWORD lpNextSize, LPDWORD lpMessageCount, LPDWORD lpReadTimeout);
+export BOOL SetMailslotInfo(HANDLE hMailslot, DWORD lReadTimeout);
+export LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap);
+export LPVOID MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap, LPVOID lpBaseAddress);
+export BOOL FlushViewOfFile(LPCVOID lpBaseAddress, DWORD dwNumberOfBytesToFlush);
+export BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);
+
+export  HGDIOBJ   GetStockObject(int);
+export BOOL ShowWindow(HWND hWnd, int nCmdShow);
+
+/* Stock Logical Objects */
+enum
+{   WHITE_BRUSH =         0,
+    LTGRAY_BRUSH =        1,
+    GRAY_BRUSH =          2,
+    DKGRAY_BRUSH =        3,
+    BLACK_BRUSH =         4,
+    NULL_BRUSH =          5,
+    HOLLOW_BRUSH =        NULL_BRUSH,
+    WHITE_PEN =           6,
+    BLACK_PEN =           7,
+    NULL_PEN =            8,
+    OEM_FIXED_FONT =      10,
+    ANSI_FIXED_FONT =     11,
+    ANSI_VAR_FONT =       12,
+    SYSTEM_FONT =         13,
+    DEVICE_DEFAULT_FONT = 14,
+    DEFAULT_PALETTE =     15,
+    SYSTEM_FIXED_FONT =   16,
+    DEFAULT_GUI_FONT =    17,
+    STOCK_LAST =          17,
+}
+
+/*
+ * ShowWindow() Commands
+ */
+enum
+{   SW_HIDE =             0,
+    SW_SHOWNORMAL =       1,
+    SW_NORMAL =           1,
+    SW_SHOWMINIMIZED =    2,
+    SW_SHOWMAXIMIZED =    3,
+    SW_MAXIMIZE =         3,
+    SW_SHOWNOACTIVATE =   4,
+    SW_SHOW =             5,
+    SW_MINIMIZE =         6,
+    SW_SHOWMINNOACTIVE =  7,
+    SW_SHOWNA =           8,
+    SW_RESTORE =          9,
+    SW_SHOWDEFAULT =      10,
+    SW_MAX =              10,
+}
+
+struct TEXTMETRICA
+{
+    LONG        tmHeight;
+    LONG        tmAscent;
+    LONG        tmDescent;
+    LONG        tmInternalLeading;
+    LONG        tmExternalLeading;
+    LONG        tmAveCharWidth;
+    LONG        tmMaxCharWidth;
+    LONG        tmWeight;
+    LONG        tmOverhang;
+    LONG        tmDigitizedAspectX;
+    LONG        tmDigitizedAspectY;
+    BYTE        tmFirstChar;
+    BYTE        tmLastChar;
+    BYTE        tmDefaultChar;
+    BYTE        tmBreakChar;
+    BYTE        tmItalic;
+    BYTE        tmUnderlined;
+    BYTE        tmStruckOut;
+    BYTE        tmPitchAndFamily;
+    BYTE        tmCharSet;
+}
+
+export  BOOL   GetTextMetricsA(HDC, TEXTMETRICA*);
+
+/*
+ * Scroll Bar Constants
+ */
+enum
+{   SB_HORZ =             0,
+    SB_VERT =             1,
+    SB_CTL =              2,
+    SB_BOTH =             3,
+}
+
+/*
+ * Scroll Bar Commands
+ */
+enum
+{   SB_LINEUP =           0,
+    SB_LINELEFT =         0,
+    SB_LINEDOWN =         1,
+    SB_LINERIGHT =        1,
+    SB_PAGEUP =           2,
+    SB_PAGELEFT =         2,
+    SB_PAGEDOWN =         3,
+    SB_PAGERIGHT =        3,
+    SB_THUMBPOSITION =    4,
+    SB_THUMBTRACK =       5,
+    SB_TOP =              6,
+    SB_LEFT =             6,
+    SB_BOTTOM =           7,
+    SB_RIGHT =            7,
+    SB_ENDSCROLL =        8,
+}
+
+export int SetScrollPos(HWND hWnd, int nBar, int nPos, BOOL bRedraw);
+export int GetScrollPos(HWND hWnd, int nBar);
+export BOOL SetScrollRange(HWND hWnd, int nBar, int nMinPos, int nMaxPos, BOOL bRedraw);
+export BOOL GetScrollRange(HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos);
+export BOOL ShowScrollBar(HWND hWnd, int wBar, BOOL bShow);
+export BOOL EnableScrollBar(HWND hWnd, UINT wSBflags, UINT wArrows);
+
+/*
+ * LockWindowUpdate API
+ */
+
+export BOOL LockWindowUpdate(HWND hWndLock);
+export BOOL ScrollWindow(HWND hWnd, int XAmount, int YAmount, RECT* lpRect, RECT* lpClipRect);
+export BOOL ScrollDC(HDC hDC, int dx, int dy, RECT* lprcScroll, RECT* lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate);
+export int ScrollWindowEx(HWND hWnd, int dx, int dy, RECT* prcScroll, RECT* prcClip, HRGN hrgnUpdate, LPRECT prcUpdate, UINT flags);
+
+/*
+ * Virtual Keys, Standard Set
+ */
+enum
+{   VK_LBUTTON =        0x01,
+    VK_RBUTTON =        0x02,
+    VK_CANCEL =         0x03,
+    VK_MBUTTON =        0x04, /* NOT contiguous with L & RBUTTON */
+
+    VK_BACK =           0x08,
+    VK_TAB =            0x09,
+
+    VK_CLEAR =          0x0C,
+    VK_RETURN =         0x0D,
+
+    VK_SHIFT =          0x10,
+    VK_CONTROL =        0x11,
+    VK_MENU =           0x12,
+    VK_PAUSE =          0x13,
+    VK_CAPITAL =        0x14,
+
+
+    VK_ESCAPE =         0x1B,
+
+    VK_SPACE =          0x20,
+    VK_PRIOR =          0x21,
+    VK_NEXT =           0x22,
+    VK_END =            0x23,
+    VK_HOME =           0x24,
+    VK_LEFT =           0x25,
+    VK_UP =             0x26,
+    VK_RIGHT =          0x27,
+    VK_DOWN =           0x28,
+    VK_SELECT =         0x29,
+    VK_PRINT =          0x2A,
+    VK_EXECUTE =        0x2B,
+    VK_SNAPSHOT =       0x2C,
+    VK_INSERT =         0x2D,
+    VK_DELETE =         0x2E,
+    VK_HELP =           0x2F,
+
+/* VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */
+/* VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
+
+    VK_LWIN =           0x5B,
+    VK_RWIN =           0x5C,
+    VK_APPS =           0x5D,
+
+    VK_NUMPAD0 =        0x60,
+    VK_NUMPAD1 =        0x61,
+    VK_NUMPAD2 =        0x62,
+    VK_NUMPAD3 =        0x63,
+    VK_NUMPAD4 =        0x64,
+    VK_NUMPAD5 =        0x65,
+    VK_NUMPAD6 =        0x66,
+    VK_NUMPAD7 =        0x67,
+    VK_NUMPAD8 =        0x68,
+    VK_NUMPAD9 =        0x69,
+    VK_MULTIPLY =       0x6A,
+    VK_ADD =            0x6B,
+    VK_SEPARATOR =      0x6C,
+    VK_SUBTRACT =       0x6D,
+    VK_DECIMAL =        0x6E,
+    VK_DIVIDE =         0x6F,
+    VK_F1 =             0x70,
+    VK_F2 =             0x71,
+    VK_F3 =             0x72,
+    VK_F4 =             0x73,
+    VK_F5 =             0x74,
+    VK_F6 =             0x75,
+    VK_F7 =             0x76,
+    VK_F8 =             0x77,
+    VK_F9 =             0x78,
+    VK_F10 =            0x79,
+    VK_F11 =            0x7A,
+    VK_F12 =            0x7B,
+    VK_F13 =            0x7C,
+    VK_F14 =            0x7D,
+    VK_F15 =            0x7E,
+    VK_F16 =            0x7F,
+    VK_F17 =            0x80,
+    VK_F18 =            0x81,
+    VK_F19 =            0x82,
+    VK_F20 =            0x83,
+    VK_F21 =            0x84,
+    VK_F22 =            0x85,
+    VK_F23 =            0x86,
+    VK_F24 =            0x87,
+
+    VK_NUMLOCK =        0x90,
+    VK_SCROLL =         0x91,
+
+/*
+ * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
+ * Used only as parameters to GetAsyncKeyState() and GetKeyState().
+ * No other API or message will distinguish left and right keys in this way.
+ */
+    VK_LSHIFT =         0xA0,
+    VK_RSHIFT =         0xA1,
+    VK_LCONTROL =       0xA2,
+    VK_RCONTROL =       0xA3,
+    VK_LMENU =          0xA4,
+    VK_RMENU =          0xA5,
+
+
+    VK_PROCESSKEY =     0xE5,
+
+
+    VK_ATTN =           0xF6,
+    VK_CRSEL =          0xF7,
+    VK_EXSEL =          0xF8,
+    VK_EREOF =          0xF9,
+    VK_PLAY =           0xFA,
+    VK_ZOOM =           0xFB,
+    VK_NONAME =         0xFC,
+    VK_PA1 =            0xFD,
+    VK_OEM_CLEAR =      0xFE,
+}
+
+export LRESULT SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+
+alias UINT (*LPOFNHOOKPROC) (HWND, UINT, WPARAM, LPARAM);
+
+struct OPENFILENAMEA {
+   DWORD        lStructSize;
+   HWND         hwndOwner;
+   HINSTANCE    hInstance;
+   LPCSTR       lpstrFilter;
+   LPSTR        lpstrCustomFilter;
+   DWORD        nMaxCustFilter;
+   DWORD        nFilterIndex;
+   LPSTR        lpstrFile;
+   DWORD        nMaxFile;
+   LPSTR        lpstrFileTitle;
+   DWORD        nMaxFileTitle;
+   LPCSTR       lpstrInitialDir;
+   LPCSTR       lpstrTitle;
+   DWORD        Flags;
+   WORD         nFileOffset;
+   WORD         nFileExtension;
+   LPCSTR       lpstrDefExt;
+   LPARAM       lCustData;
+   LPOFNHOOKPROC lpfnHook;
+   LPCSTR       lpTemplateName;
+}
+alias OPENFILENAMEA *LPOPENFILENAMEA;
+
+struct OPENFILENAMEW {
+   DWORD        lStructSize;
+   HWND         hwndOwner;
+   HINSTANCE    hInstance;
+   LPCWSTR      lpstrFilter;
+   LPWSTR       lpstrCustomFilter;
+   DWORD        nMaxCustFilter;
+   DWORD        nFilterIndex;
+   LPWSTR       lpstrFile;
+   DWORD        nMaxFile;
+   LPWSTR       lpstrFileTitle;
+   DWORD        nMaxFileTitle;
+   LPCWSTR      lpstrInitialDir;
+   LPCWSTR      lpstrTitle;
+   DWORD        Flags;
+   WORD         nFileOffset;
+   WORD         nFileExtension;
+   LPCWSTR      lpstrDefExt;
+   LPARAM       lCustData;
+   LPOFNHOOKPROC lpfnHook;
+   LPCWSTR      lpTemplateName;
+}
+alias OPENFILENAMEW *LPOPENFILENAMEW;
+
+BOOL          GetOpenFileNameA(LPOPENFILENAMEA);
+BOOL          GetOpenFileNameW(LPOPENFILENAMEW);
+
+BOOL          GetSaveFileNameA(LPOPENFILENAMEA);
+BOOL          GetSaveFileNameW(LPOPENFILENAMEW);
+
+short         GetFileTitleA(LPCSTR, LPSTR, WORD);
+short         GetFileTitleW(LPCWSTR, LPWSTR, WORD);
+
+enum
+{
+    PM_NOREMOVE =         0x0000,
+    PM_REMOVE =           0x0001,
+    PM_NOYIELD =          0x0002,
+}
+
+/* Bitmap Header Definition */
+struct BITMAP
+{
+    LONG        bmType;
+    LONG        bmWidth;
+    LONG        bmHeight;
+    LONG        bmWidthBytes;
+    WORD        bmPlanes;
+    WORD        bmBitsPixel;
+    LPVOID      bmBits;
+}
+alias BITMAP* PBITMAP, NPBITMAP, LPBITMAP;
+
+
+export  HDC       CreateCompatibleDC(HDC);
+
+export  int     GetObjectA(HGDIOBJ, int, LPVOID);
+export  int     GetObjectW(HGDIOBJ, int, LPVOID);
+export  BOOL   DeleteDC(HDC);
+
+struct LOGFONTA
+{
+    LONG      lfHeight;
+    LONG      lfWidth;
+    LONG      lfEscapement;
+    LONG      lfOrientation;
+    LONG      lfWeight;
+    BYTE      lfItalic;
+    BYTE      lfUnderline;
+    BYTE      lfStrikeOut;
+    BYTE      lfCharSet;
+    BYTE      lfOutPrecision;
+    BYTE      lfClipPrecision;
+    BYTE      lfQuality;
+    BYTE      lfPitchAndFamily;
+    CHAR      lfFaceName[32 ];
+}
+alias LOGFONTA* PLOGFONTA, NPLOGFONTA, LPLOGFONTA;
+
+export HMENU LoadMenuA(HINSTANCE hInstance, LPCSTR lpMenuName);
+export HMENU LoadMenuW(HINSTANCE hInstance, LPCWSTR lpMenuName);
+
+export HMENU GetSubMenu(HMENU hMenu, int nPos);
+
+export HBITMAP LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName);
+export HBITMAP LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName);
+
+LPSTR MAKEINTRESOURCEA(int i) { return cast(LPSTR)(cast(DWORD)(cast(WORD)(i))); }
+
+export  HFONT     CreateFontIndirectA(LOGFONTA *);
+
+export BOOL MessageBeep(UINT uType);
+export int ShowCursor(BOOL bShow);
+export BOOL SetCursorPos(int X, int Y);
+export HCURSOR SetCursor(HCURSOR hCursor);
+export BOOL GetCursorPos(LPPOINT lpPoint);
+export BOOL ClipCursor( RECT *lpRect);
+export BOOL GetClipCursor(LPRECT lpRect);
+export HCURSOR GetCursor();
+export BOOL CreateCaret(HWND hWnd, HBITMAP hBitmap , int nWidth, int nHeight);
+export UINT GetCaretBlinkTime();
+export BOOL SetCaretBlinkTime(UINT uMSeconds);
+export BOOL DestroyCaret();
+export BOOL HideCaret(HWND hWnd);
+export BOOL ShowCaret(HWND hWnd);
+export BOOL SetCaretPos(int X, int Y);
+export BOOL GetCaretPos(LPPOINT lpPoint);
+export BOOL ClientToScreen(HWND hWnd, LPPOINT lpPoint);
+export BOOL ScreenToClient(HWND hWnd, LPPOINT lpPoint);
+export int MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints);
+export HWND WindowFromPoint(POINT Point);
+export HWND ChildWindowFromPoint(HWND hWndParent, POINT Point);
+
+
+export BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y,
+    int nReserved, HWND hWnd, RECT *prcRect);
+
+align (2) struct DLGTEMPLATE {
+    DWORD style;
+    DWORD dwExtendedStyle;
+    WORD cdit;
+    short x;
+    short y;
+    short cx;
+    short cy;
+}
+alias DLGTEMPLATE *LPDLGTEMPLATEA;
+alias DLGTEMPLATE *LPDLGTEMPLATEW;
+
+
+alias LPDLGTEMPLATEA LPDLGTEMPLATE;
+
+alias  DLGTEMPLATE *LPCDLGTEMPLATEA;
+alias  DLGTEMPLATE *LPCDLGTEMPLATEW;
+
+
+alias LPCDLGTEMPLATEA LPCDLGTEMPLATE;
+
+
+export int DialogBoxParamA(HINSTANCE hInstance, LPCSTR lpTemplateName,
+    HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);
+export int DialogBoxIndirectParamA(HINSTANCE hInstance,
+    LPCDLGTEMPLATEA hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc,
+    LPARAM dwInitParam);
+
+enum : DWORD
+{
+    SRCCOPY =             cast(DWORD)0x00CC0020, /* dest = source                   */
+    SRCPAINT =            cast(DWORD)0x00EE0086, /* dest = source OR dest           */
+    SRCAND =              cast(DWORD)0x008800C6, /* dest = source AND dest          */
+    SRCINVERT =           cast(DWORD)0x00660046, /* dest = source XOR dest          */
+    SRCERASE =            cast(DWORD)0x00440328, /* dest = source AND (NOT dest)   */
+    NOTSRCCOPY =          cast(DWORD)0x00330008, /* dest = (NOT source)             */
+    NOTSRCERASE =         cast(DWORD)0x001100A6, /* dest = (NOT src) AND (NOT dest) */
+    MERGECOPY =           cast(DWORD)0x00C000CA, /* dest = (source AND pattern)     */
+    MERGEPAINT =          cast(DWORD)0x00BB0226, /* dest = (NOT source) OR dest     */
+    PATCOPY =             cast(DWORD)0x00F00021, /* dest = pattern                  */
+    PATPAINT =            cast(DWORD)0x00FB0A09, /* dest = DPSnoo                   */
+    PATINVERT =           cast(DWORD)0x005A0049, /* dest = pattern XOR dest         */
+    DSTINVERT =           cast(DWORD)0x00550009, /* dest = (NOT dest)               */
+    BLACKNESS =           cast(DWORD)0x00000042, /* dest = BLACK                    */
+    WHITENESS =           cast(DWORD)0x00FF0062, /* dest = WHITE                    */
+}
+
+enum
+{
+    SND_SYNC =            0x0000, /* play synchronously (default) */
+    SND_ASYNC =           0x0001, /* play asynchronously */
+    SND_NODEFAULT =       0x0002, /* silence (!default) if sound not found */
+    SND_MEMORY =          0x0004, /* pszSound points to a memory file */
+    SND_LOOP =            0x0008, /* loop the sound until next sndPlaySound */
+    SND_NOSTOP =          0x0010, /* don't stop any currently playing sound */
+
+    SND_NOWAIT =    0x00002000, /* don't wait if the driver is busy */
+    SND_ALIAS =       0x00010000, /* name is a registry alias */
+    SND_ALIAS_ID =  0x00110000, /* alias is a predefined ID */
+    SND_FILENAME =    0x00020000, /* name is file name */
+    SND_RESOURCE =    0x00040004, /* name is resource name or atom */
+
+    SND_PURGE =           0x0040, /* purge non-static events for task */
+    SND_APPLICATION =     0x0080, /* look for application specific association */
+
+
+    SND_ALIAS_START =   0,     /* alias base */
+}
+
+export  BOOL   PlaySoundA(LPCSTR pszSound, HMODULE hmod, DWORD fdwSound);
+export  BOOL   PlaySoundW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound);
+
+export  int     GetClipBox(HDC, LPRECT);
+export  int     GetClipRgn(HDC, HRGN);
+export  int     GetMetaRgn(HDC, HRGN);
+export  HGDIOBJ   GetCurrentObject(HDC, UINT);
+export  BOOL    GetCurrentPositionEx(HDC, LPPOINT);
+export  int     GetDeviceCaps(HDC, int);
+
+struct LOGPEN
+  {
+    UINT        lopnStyle;
+    POINT       lopnWidth;
+    COLORREF    lopnColor;
+}
+alias LOGPEN* PLOGPEN, NPLOGPEN, LPLOGPEN;
+
+enum
+{
+    PS_SOLID =            0,
+    PS_DASH =             1, /* -------  */
+    PS_DOT =              2, /* .......  */
+    PS_DASHDOT =          3, /* _._._._  */
+    PS_DASHDOTDOT =       4, /* _.._.._  */
+    PS_NULL =             5,
+    PS_INSIDEFRAME =      6,
+    PS_USERSTYLE =        7,
+    PS_ALTERNATE =        8,
+    PS_STYLE_MASK =       0x0000000F,
+
+    PS_ENDCAP_ROUND =     0x00000000,
+    PS_ENDCAP_SQUARE =    0x00000100,
+    PS_ENDCAP_FLAT =      0x00000200,
+    PS_ENDCAP_MASK =      0x00000F00,
+
+    PS_JOIN_ROUND =       0x00000000,
+    PS_JOIN_BEVEL =       0x00001000,
+    PS_JOIN_MITER =       0x00002000,
+    PS_JOIN_MASK =        0x0000F000,
+
+    PS_COSMETIC =         0x00000000,
+    PS_GEOMETRIC =        0x00010000,
+    PS_TYPE_MASK =        0x000F0000,
+}
+
+export  HPALETTE   CreatePalette(LOGPALETTE *);
+export  HPEN      CreatePen(int, int, COLORREF);
+export  HPEN      CreatePenIndirect(LOGPEN *);
+export  HRGN      CreatePolyPolygonRgn(POINT *, INT *, int, int);
+export  HBRUSH    CreatePatternBrush(HBITMAP);
+export  HRGN      CreateRectRgn(int, int, int, int);
+export  HRGN      CreateRectRgnIndirect(RECT *);
+export  HRGN      CreateRoundRectRgn(int, int, int, int, int, int);
+export  BOOL      CreateScalableFontResourceA(DWORD, LPCSTR, LPCSTR, LPCSTR);
+export  BOOL      CreateScalableFontResourceW(DWORD, LPCWSTR, LPCWSTR, LPCWSTR);
+
+COLORREF RGB(int r, int g, int b)
+{
+    return cast(COLORREF)
+    ((cast(BYTE)r|(cast(WORD)(cast(BYTE)g)<<8))|((cast(DWORD)cast(BYTE)b)<<16));
+}
+
+export  BOOL   LineTo(HDC, int, int);
+export  BOOL   DeleteObject(HGDIOBJ);
+export int FillRect(HDC hDC,  RECT *lprc, HBRUSH hbr);
+
+
+export BOOL EndDialog(HWND hDlg, int nResult);
+export HWND GetDlgItem(HWND hDlg, int nIDDlgItem);
+
+export BOOL SetDlgItemInt(HWND hDlg, int nIDDlgItem, UINT uValue, BOOL bSigned);
+export UINT GetDlgItemInt(HWND hDlg, int nIDDlgItem, BOOL *lpTranslated,
+    BOOL bSigned);
+
+export BOOL SetDlgItemTextA(HWND hDlg, int nIDDlgItem, LPCSTR lpString);
+export BOOL SetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPCWSTR lpString);
+
+export UINT GetDlgItemTextA(HWND hDlg, int nIDDlgItem, LPSTR lpString, int nMaxCount);
+export UINT GetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPWSTR lpString, int nMaxCount);
+
+export BOOL CheckDlgButton(HWND hDlg, int nIDButton, UINT uCheck);
+export BOOL CheckRadioButton(HWND hDlg, int nIDFirstButton, int nIDLastButton,
+    int nIDCheckButton);
+
+export UINT IsDlgButtonChecked(HWND hDlg, int nIDButton);
+
+export HWND SetFocus(HWND hWnd);
+
+export int wsprintfA(LPSTR, LPCSTR, ...);
+export int wsprintfW(LPWSTR, LPCWSTR, ...);
+
+enum : uint
+{
+    INFINITE =              uint.max,
+    WAIT_OBJECT_0 =         0,
+    WAIT_ABANDONED_0 =      0x80,
+    WAIT_TIMEOUT =          0x102,
+    WAIT_IO_COMPLETION =    0xc0,
+    WAIT_ABANDONED =        0x80,
+    WAIT_FAILED =           uint.max,
+}
+
+export HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName);
+export HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);
+export BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount);
+
+struct COORD {
+    SHORT X;
+    SHORT Y;
+}
+alias COORD *PCOORD;
+
+struct SMALL_RECT {
+    SHORT Left;
+    SHORT Top;
+    SHORT Right;
+    SHORT Bottom;
+}
+alias SMALL_RECT *PSMALL_RECT;
+
+struct KEY_EVENT_RECORD {
+    BOOL bKeyDown;
+    WORD wRepeatCount;
+    WORD wVirtualKeyCode;
+    WORD wVirtualScanCode;
+    union {
+        WCHAR UnicodeChar;
+        CHAR   AsciiChar;
+    }
+    DWORD dwControlKeyState;
+}
+alias KEY_EVENT_RECORD *PKEY_EVENT_RECORD;
+
+//
+// ControlKeyState flags
+//
+
+enum
+{
+    RIGHT_ALT_PRESSED =     0x0001, // the right alt key is pressed.
+    LEFT_ALT_PRESSED =      0x0002, // the left alt key is pressed.
+    RIGHT_CTRL_PRESSED =    0x0004, // the right ctrl key is pressed.
+    LEFT_CTRL_PRESSED =     0x0008, // the left ctrl key is pressed.
+    SHIFT_PRESSED =         0x0010, // the shift key is pressed.
+    NUMLOCK_ON =            0x0020, // the numlock light is on.
+    SCROLLLOCK_ON =         0x0040, // the scrolllock light is on.
+    CAPSLOCK_ON =           0x0080, // the capslock light is on.
+    ENHANCED_KEY =          0x0100, // the key is enhanced.
+}
+
+struct MOUSE_EVENT_RECORD {
+    COORD dwMousePosition;
+    DWORD dwButtonState;
+    DWORD dwControlKeyState;
+    DWORD dwEventFlags;
+}
+alias MOUSE_EVENT_RECORD *PMOUSE_EVENT_RECORD;
+
+//
+// ButtonState flags
+//
+enum
+{
+    FROM_LEFT_1ST_BUTTON_PRESSED =    0x0001,
+    RIGHTMOST_BUTTON_PRESSED =        0x0002,
+    FROM_LEFT_2ND_BUTTON_PRESSED =    0x0004,
+    FROM_LEFT_3RD_BUTTON_PRESSED =    0x0008,
+    FROM_LEFT_4TH_BUTTON_PRESSED =    0x0010,
+}
+
+//
+// EventFlags
+//
+
+enum
+{
+    MOUSE_MOVED =   0x0001,
+    DOUBLE_CLICK =  0x0002,
+}
+
+struct WINDOW_BUFFER_SIZE_RECORD {
+    COORD dwSize;
+}
+alias WINDOW_BUFFER_SIZE_RECORD *PWINDOW_BUFFER_SIZE_RECORD;
+
+struct MENU_EVENT_RECORD {
+    UINT dwCommandId;
+}
+alias MENU_EVENT_RECORD *PMENU_EVENT_RECORD;
+
+struct FOCUS_EVENT_RECORD {
+    BOOL bSetFocus;
+}
+alias FOCUS_EVENT_RECORD *PFOCUS_EVENT_RECORD;
+
+struct INPUT_RECORD {
+    WORD EventType;
+    union {
+        KEY_EVENT_RECORD KeyEvent;
+        MOUSE_EVENT_RECORD MouseEvent;
+        WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
+        MENU_EVENT_RECORD MenuEvent;
+        FOCUS_EVENT_RECORD FocusEvent;
+    }
+}
+alias INPUT_RECORD *PINPUT_RECORD;
+
+//
+//  EventType flags:
+//
+
+enum
+{
+    KEY_EVENT =         0x0001, // Event contains key event record
+    MOUSE_EVENT =       0x0002, // Event contains mouse event record
+    WINDOW_BUFFER_SIZE_EVENT = 0x0004, // Event contains window change event record
+    MENU_EVENT = 0x0008, // Event contains menu event record
+    FOCUS_EVENT = 0x0010, // event contains focus change
+}
+
+struct CHAR_INFO {
+    union {
+        WCHAR UnicodeChar;
+        CHAR   AsciiChar;
+    }
+    WORD Attributes;
+}
+alias CHAR_INFO *PCHAR_INFO;
+
+//
+// Attributes flags:
+//
+
+enum
+{
+    FOREGROUND_BLUE =      0x0001, // text color contains blue.
+    FOREGROUND_GREEN =     0x0002, // text color contains green.
+    FOREGROUND_RED =       0x0004, // text color contains red.
+    FOREGROUND_INTENSITY = 0x0008, // text color is intensified.
+    BACKGROUND_BLUE =      0x0010, // background color contains blue.
+    BACKGROUND_GREEN =     0x0020, // background color contains green.
+    BACKGROUND_RED =       0x0040, // background color contains red.
+    BACKGROUND_INTENSITY = 0x0080, // background color is intensified.
+}
+
+struct CONSOLE_SCREEN_BUFFER_INFO {
+    COORD dwSize;
+    COORD dwCursorPosition;
+    WORD  wAttributes;
+    SMALL_RECT srWindow;
+    COORD dwMaximumWindowSize;
+}
+alias CONSOLE_SCREEN_BUFFER_INFO *PCONSOLE_SCREEN_BUFFER_INFO;
+
+struct CONSOLE_CURSOR_INFO {
+    DWORD  dwSize;
+    BOOL   bVisible;
+}
+alias CONSOLE_CURSOR_INFO *PCONSOLE_CURSOR_INFO;
+
+enum
+{
+    ENABLE_PROCESSED_INPUT = 0x0001,
+    ENABLE_LINE_INPUT =      0x0002,
+    ENABLE_ECHO_INPUT =      0x0004,
+    ENABLE_WINDOW_INPUT =    0x0008,
+    ENABLE_MOUSE_INPUT =     0x0010,
+}
+
+enum
+{
+    ENABLE_PROCESSED_OUTPUT =    0x0001,
+    ENABLE_WRAP_AT_EOL_OUTPUT =  0x0002,
+}
+
+BOOL PeekConsoleInputA(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL PeekConsoleInputW(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL ReadConsoleInputA(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL ReadConsoleInputW(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL WriteConsoleInputA(HANDLE hConsoleInput, in INPUT_RECORD *lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsWritten);
+BOOL WriteConsoleInputW(HANDLE hConsoleInput, in INPUT_RECORD *lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsWritten);
+BOOL ReadConsoleOutputA(HANDLE hConsoleOutput, PCHAR_INFO lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpReadRegion);
+BOOL ReadConsoleOutputW(HANDLE hConsoleOutput, PCHAR_INFO lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpReadRegion);
+BOOL WriteConsoleOutputA(HANDLE hConsoleOutput, in CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpWriteRegion);
+BOOL WriteConsoleOutputW(HANDLE hConsoleOutput, in CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpWriteRegion);
+BOOL ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, LPSTR lpCharacter, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead);
+BOOL ReadConsoleOutputCharacterW(HANDLE hConsoleOutput, LPWSTR lpCharacter, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead);
+BOOL ReadConsoleOutputAttribute(HANDLE hConsoleOutput, LPWORD lpAttribute, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfAttrsRead);
+BOOL WriteConsoleOutputCharacterA(HANDLE hConsoleOutput, LPCSTR lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL WriteConsoleOutputCharacterW(HANDLE hConsoleOutput, LPCWSTR lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL WriteConsoleOutputAttribute(HANDLE hConsoleOutput, in WORD *lpAttribute, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten);
+BOOL FillConsoleOutputCharacterA(HANDLE hConsoleOutput, CHAR cCharacter, DWORD  nLength, COORD  dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL FillConsoleOutputCharacterW(HANDLE hConsoleOutput, WCHAR cCharacter, DWORD  nLength, COORD  dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL FillConsoleOutputAttribute(HANDLE hConsoleOutput, WORD   wAttribute, DWORD  nLength, COORD  dwWriteCoord, LPDWORD lpNumberOfAttrsWritten);
+BOOL GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode);
+BOOL GetNumberOfConsoleInputEvents(HANDLE hConsoleInput, LPDWORD lpNumberOfEvents);
+BOOL GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
+COORD GetLargestConsoleWindowSize( HANDLE hConsoleOutput);
+BOOL GetConsoleCursorInfo(HANDLE hConsoleOutput, PCONSOLE_CURSOR_INFO lpConsoleCursorInfo);
+BOOL GetNumberOfConsoleMouseButtons( LPDWORD lpNumberOfMouseButtons);
+BOOL SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode);
+BOOL SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput);
+BOOL FlushConsoleInputBuffer(HANDLE hConsoleInput);
+BOOL SetConsoleScreenBufferSize(HANDLE hConsoleOutput, COORD dwSize);
+BOOL SetConsoleCursorPosition(HANDLE hConsoleOutput, COORD dwCursorPosition);
+BOOL SetConsoleCursorInfo(HANDLE hConsoleOutput, in CONSOLE_CURSOR_INFO *lpConsoleCursorInfo);
+BOOL ScrollConsoleScreenBufferA(HANDLE hConsoleOutput, in SMALL_RECT *lpScrollRectangle, in SMALL_RECT *lpClipRectangle, COORD dwDestinationOrigin, in CHAR_INFO *lpFill);
+BOOL ScrollConsoleScreenBufferW(HANDLE hConsoleOutput, in SMALL_RECT *lpScrollRectangle, in SMALL_RECT *lpClipRectangle, COORD dwDestinationOrigin, in CHAR_INFO *lpFill);
+BOOL SetConsoleWindowInfo(HANDLE hConsoleOutput, BOOL bAbsolute, in SMALL_RECT *lpConsoleWindow);
+BOOL SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes);
+alias BOOL(*PHANDLER_ROUTINE)(DWORD CtrlType);
+BOOL SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add);
+BOOL GenerateConsoleCtrlEvent( DWORD dwCtrlEvent, DWORD dwProcessGroupId);
+BOOL AllocConsole();
+BOOL FreeConsole();
+DWORD GetConsoleTitleA(LPSTR lpConsoleTitle, DWORD nSize);
+DWORD GetConsoleTitleW(LPWSTR lpConsoleTitle, DWORD nSize);
+BOOL SetConsoleTitleA(LPCSTR lpConsoleTitle);
+BOOL SetConsoleTitleW(LPCWSTR lpConsoleTitle);
+BOOL ReadConsoleA(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved);
+BOOL ReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved);
+BOOL WriteConsoleA(HANDLE hConsoleOutput, in  void *lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved);
+BOOL WriteConsoleW(HANDLE hConsoleOutput, in  void *lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved);
+HANDLE CreateConsoleScreenBuffer(DWORD dwDesiredAccess, DWORD dwShareMode, in SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwFlags, LPVOID lpScreenBufferData);
+UINT GetConsoleCP();
+BOOL SetConsoleCP( UINT wCodePageID);
+UINT GetConsoleOutputCP();
+BOOL SetConsoleOutputCP(UINT wCodePageID);
+
+enum
+{
+    CONSOLE_TEXTMODE_BUFFER = 1,
+}
+
+enum
+{
+    SM_CXSCREEN =             0,
+    SM_CYSCREEN =             1,
+    SM_CXVSCROLL =            2,
+    SM_CYHSCROLL =            3,
+    SM_CYCAPTION =            4,
+    SM_CXBORDER =             5,
+    SM_CYBORDER =             6,
+    SM_CXDLGFRAME =           7,
+    SM_CYDLGFRAME =           8,
+    SM_CYVTHUMB =             9,
+    SM_CXHTHUMB =             10,
+    SM_CXICON =               11,
+    SM_CYICON =               12,
+    SM_CXCURSOR =             13,
+    SM_CYCURSOR =             14,
+    SM_CYMENU =               15,
+    SM_CXFULLSCREEN =         16,
+    SM_CYFULLSCREEN =         17,
+    SM_CYKANJIWINDOW =        18,
+    SM_MOUSEPRESENT =         19,
+    SM_CYVSCROLL =            20,
+    SM_CXHSCROLL =            21,
+    SM_DEBUG =                22,
+    SM_SWAPBUTTON =           23,
+    SM_RESERVED1 =            24,
+    SM_RESERVED2 =            25,
+    SM_RESERVED3 =            26,
+    SM_RESERVED4 =            27,
+    SM_CXMIN =                28,
+    SM_CYMIN =                29,
+    SM_CXSIZE =               30,
+    SM_CYSIZE =               31,
+    SM_CXFRAME =              32,
+    SM_CYFRAME =              33,
+    SM_CXMINTRACK =           34,
+    SM_CYMINTRACK =           35,
+    SM_CXDOUBLECLK =          36,
+    SM_CYDOUBLECLK =          37,
+    SM_CXICONSPACING =        38,
+    SM_CYICONSPACING =        39,
+    SM_MENUDROPALIGNMENT =    40,
+    SM_PENWINDOWS =           41,
+    SM_DBCSENABLED =          42,
+    SM_CMOUSEBUTTONS =        43,
+
+
+    SM_CXFIXEDFRAME =         SM_CXDLGFRAME,
+    SM_CYFIXEDFRAME =         SM_CYDLGFRAME,
+    SM_CXSIZEFRAME =          SM_CXFRAME,
+    SM_CYSIZEFRAME =          SM_CYFRAME,
+
+    SM_SECURE =               44,
+    SM_CXEDGE =               45,
+    SM_CYEDGE =               46,
+    SM_CXMINSPACING =         47,
+    SM_CYMINSPACING =         48,
+    SM_CXSMICON =             49,
+    SM_CYSMICON =             50,
+    SM_CYSMCAPTION =          51,
+    SM_CXSMSIZE =             52,
+    SM_CYSMSIZE =             53,
+    SM_CXMENUSIZE =           54,
+    SM_CYMENUSIZE =           55,
+    SM_ARRANGE =              56,
+    SM_CXMINIMIZED =          57,
+    SM_CYMINIMIZED =          58,
+    SM_CXMAXTRACK =           59,
+    SM_CYMAXTRACK =           60,
+    SM_CXMAXIMIZED =          61,
+    SM_CYMAXIMIZED =          62,
+    SM_NETWORK =              63,
+    SM_CLEANBOOT =            67,
+    SM_CXDRAG =               68,
+    SM_CYDRAG =               69,
+    SM_SHOWSOUNDS =           70,
+    SM_CXMENUCHECK =          71,
+    SM_CYMENUCHECK =          72,
+    SM_SLOWMACHINE =          73,
+    SM_MIDEASTENABLED =       74,
+    SM_CMETRICS =             75,
+}
+
+int GetSystemMetrics(int nIndex);
+
+enum : DWORD
+{
+    STILL_ACTIVE = (0x103),
+}
+
+DWORD TlsAlloc();
+LPVOID TlsGetValue(DWORD);
+BOOL TlsSetValue(DWORD, LPVOID);
+BOOL TlsFree(DWORD);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/object.di	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,268 @@
+/**
+ * Contains all implicitly declared types and variables.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module object;
+
+alias typeof(int.sizeof)                    size_t;
+alias typeof(cast(void*)0 - cast(void*)0)   ptrdiff_t;
+
+alias size_t hash_t;
+alias bool equals_t;
+
+alias immutable(char)[]  string;
+alias immutable(wchar)[] wstring;
+alias immutable(dchar)[] dstring;
+
+class Object
+{
+    string   toString();
+    hash_t   toHash();
+    int      opCmp(Object o);
+    equals_t opEquals(Object o);
+
+    interface Monitor
+    {
+        void lock();
+        void unlock();
+    }
+
+    static Object factory(string classname);
+}
+
+struct Interface
+{
+    ClassInfo   classinfo;
+    void*[]     vtbl;
+    ptrdiff_t   offset;   // offset to Interface 'this' from Object 'this'
+}
+
+class ClassInfo : Object
+{
+    byte[]      init;   // class static initializer
+    string      name;   // class name
+    void*[]     vtbl;   // virtual function pointer table
+    Interface[] interfaces;
+    ClassInfo   base;
+    void*       destructor;
+    void(*classInvariant)(Object);
+    uint        flags;
+    //  1:      // is IUnknown or is derived from IUnknown
+    //  2:      // has no possible pointers into GC memory
+    //  4:      // has offTi[] member
+    //  8:      // has constructors
+    // 16:      // has xgetMembers member
+    // 32:      // has typeinfo member
+    void*       deallocator;
+    OffsetTypeInfo[] offTi;
+    void*       defaultConstructor;
+    const(MemberInfo[]) function(string) xgetMembers;
+    TypeInfo    typeinfo;
+
+    static ClassInfo find(in char[] classname);
+    Object create();
+    const(MemberInfo[]) getMembers(in char[] classname);
+}
+
+struct OffsetTypeInfo
+{
+    size_t   offset;
+    TypeInfo ti;
+}
+
+class TypeInfo
+{
+    hash_t   getHash(in void* p);
+    equals_t equals(in void* p1, in void* p2);
+    int      compare(in void* p1, in void* p2);
+    size_t   tsize();
+    void     swap(void* p1, void* p2);
+    TypeInfo next();
+    void[]   init();
+    uint     flags();
+    // 1:    // has possible pointers into GC memory
+    OffsetTypeInfo[] offTi();
+    void destroy(void* p);
+    void postblit(void* p);
+}
+
+class TypeInfo_Typedef : TypeInfo
+{
+    TypeInfo base;
+    string   name;
+    void[]   m_init;
+}
+
+class TypeInfo_Enum : TypeInfo_Typedef
+{
+
+}
+
+class TypeInfo_Pointer : TypeInfo
+{
+    TypeInfo m_next;
+}
+
+class TypeInfo_Array : TypeInfo
+{
+    TypeInfo value;
+}
+
+class TypeInfo_StaticArray : TypeInfo
+{
+    TypeInfo value;
+    size_t   len;
+}
+
+class TypeInfo_AssociativeArray : TypeInfo
+{
+    TypeInfo value;
+    TypeInfo key;
+}
+
+class TypeInfo_Function : TypeInfo
+{
+    TypeInfo next;
+}
+
+class TypeInfo_Delegate : TypeInfo
+{
+    TypeInfo next;
+}
+
+class TypeInfo_Class : TypeInfo
+{
+    ClassInfo info;
+}
+
+class TypeInfo_Interface : TypeInfo
+{
+    ClassInfo info;
+}
+
+class TypeInfo_Struct : TypeInfo
+{
+    string name;
+    void[] m_init;
+
+    uint function(in void*)               xtoHash;
+    equals_t function(in void*, in void*) xopEquals;
+    int function(in void*, in void*)      xopCmp;
+    string function(in void*)             xtoString;
+
+    uint m_flags;
+
+    const(MemberInfo[]) function(in char[]) xgetMembers;
+    void function(void*)                    xdtor;
+    void function(void*)                    xpostblit;
+}
+
+class TypeInfo_Tuple : TypeInfo
+{
+    TypeInfo[]  elements;
+}
+
+class TypeInfo_Const : TypeInfo
+{
+    TypeInfo next;
+}
+
+class TypeInfo_Invariant : TypeInfo_Const
+{
+
+}
+
+class TypeInfo_Shared : TypeInfo_Const
+{
+
+}
+
+abstract class MemberInfo
+{
+    string name();
+}
+
+class MemberInfo_field : MemberInfo
+{
+    this(string name, TypeInfo ti, size_t offset);
+
+    override string name();
+    TypeInfo typeInfo();
+    size_t offset();
+}
+
+class MemberInfo_function : MemberInfo
+{
+    enum
+    {
+        Virtual = 1,
+        Member  = 2,
+        Static  = 4,
+    }
+
+    this(string name, TypeInfo ti, void* fp, uint flags);
+
+    override string name();
+    TypeInfo typeInfo();
+    void* fp();
+    uint flags();
+}
+
+class ModuleInfo
+{
+    string          name;
+    ModuleInfo[]    importedModules;
+    ClassInfo[]     localClasses;
+    uint            flags;
+
+    void function() ctor;
+    void function() dtor;
+    void function() unitTest;
+
+    void*           xgetMembers;
+    void function() ictor;
+    void*[4] reserved;
+
+    static int opApply(int delegate(inout ModuleInfo));
+}
+
+class Throwable : Object
+{
+    interface TraceInfo
+    {
+        int opApply(int delegate(inout char[]));
+        string toString();
+    }
+
+    string      msg;
+    string      file;
+    size_t      line;
+    TraceInfo   info;
+    Throwable   next;
+
+    this(string msg, Throwable next = null);
+    this(string msg, string file, size_t line, Throwable next = null);
+    override string toString();
+}
+
+
+class Exception : Throwable
+{
+    this(string msg, Throwable next = null);
+    this(string msg, string file, size_t line, Throwable next = null);
+}
+
+
+class Error : Throwable
+{
+    this(string msg, Throwable next = null);
+    this(string msg, string file, size_t line, Throwable next = null);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/std/c/stdarg.di	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,32 @@
+/**
+ * These functions are built-in intrinsics to the compiler.
+ *
+ * Copyright: Public Domain
+ * License:   Public Domain
+ * Authors:   David Friedman
+ */
+module std.c.stdarg;
+
+version( GNU )
+{
+    private import gcc.builtins;
+    alias __builtin_va_list va_list;
+    alias __builtin_va_end  va_end;
+    alias __builtin_va_copy va_copy;
+}
+
+template va_start(T)
+{
+    void va_start( out va_list ap, inout T parmn )
+    {
+
+    }
+}
+
+template va_arg(T)
+{
+    T va_arg( inout va_list ap )
+    {
+        return T.init;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/std/intrinsic.di	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,176 @@
+/**
+ * These functions are built-in intrinsics to the compiler.
+ *
+ * Intrinsic functions are functions built in to the compiler, usually to take
+ * advantage of specific CPU features that are inefficient to handle via
+ * external functions.  The compiler's optimizer and code generator are fully
+ * integrated in with intrinsic functions, bringing to bear their full power on
+ * them. This can result in some surprising speedups.
+ *
+ * Copyright: Public Domain
+ * License:   Public Domain
+ * Authors:   Walter Bright
+ */
+module std.intrinsic;
+
+
+/**
+ * Scans the bits in v starting with bit 0, looking
+ * for the first set bit.
+ * Returns:
+ *      The bit number of the first bit set.
+ *      The return value is undefined if v is zero.
+ */
+pure nothrow int bsf( uint v );
+
+
+/**
+ * Scans the bits in v from the most significant bit
+ * to the least significant bit, looking
+ * for the first set bit.
+ * Returns:
+ *      The bit number of the first bit set.
+ *      The return value is undefined if v is zero.
+ * Example:
+ * ---
+ * import std.intrinsic;
+ *
+ * int main()
+ * {
+ *     uint v;
+ *     int x;
+ *
+ *     v = 0x21;
+ *     x = bsf(v);
+ *     printf("bsf(x%x) = %d\n", v, x);
+ *     x = bsr(v);
+ *     printf("bsr(x%x) = %d\n", v, x);
+ *     return 0;
+ * }
+ * ---
+ * Output:
+ *  bsf(x21) = 0<br>
+ *  bsr(x21) = 5
+ */
+pure nothrow int bsr( uint v );
+
+
+/**
+ * Tests the bit.
+ */
+pure nothrow int bt( in uint* p, uint bitnum );
+
+
+/**
+ * Tests and complements the bit.
+ */
+nothrow int btc( uint* p, uint bitnum );
+
+
+/**
+ * Tests and resets (sets to 0) the bit.
+ */
+nothrow int btr( uint* p, uint bitnum );
+
+
+/**
+ * Tests and sets the bit.
+ * Params:
+ * p = a non-NULL pointer to an array of uints.
+ * index = a bit number, starting with bit 0 of p[0],
+ * and progressing. It addresses bits like the expression:
+---
+p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)))
+---
+ * Returns:
+ *      A non-zero value if the bit was set, and a zero
+ *      if it was clear.
+ *
+ * Example:
+ * ---
+import std.intrinsic;
+
+int main()
+{
+    uint array[2];
+
+    array[0] = 2;
+    array[1] = 0x100;
+
+    printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
+    printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+    printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
+    printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+    printf("bts(array, 35) = %d\n", <b>bts</b>(array, 35));
+    printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+    printf("btr(array, 35) = %d\n", <b>btr</b>(array, 35));
+    printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+    printf("bt(array, 1) = %d\n", <b>bt</b>(array, 1));
+    printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+    return 0;
+}
+ * ---
+ * Output:
+<pre>
+btc(array, 35) = 0
+array = [0]:x2, [1]:x108
+btc(array, 35) = -1
+array = [0]:x2, [1]:x100
+bts(array, 35) = 0
+array = [0]:x2, [1]:x108
+btr(array, 35) = -1
+array = [0]:x2, [1]:x100
+bt(array, 1) = -1
+array = [0]:x2, [1]:x100
+</pre>
+ */
+nothrow int bts( uint* p, uint bitnum );
+
+
+/**
+ * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes
+ * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3
+ * becomes byte 0.
+ */
+pure nothrow uint bswap( uint v );
+
+
+/**
+ * Reads I/O port at port_address.
+ */
+nothrow ubyte inp( uint port_address );
+
+
+/**
+ * ditto
+ */
+nothrow ushort inpw( uint port_address );
+
+
+/**
+ * ditto
+ */
+nothrow uint inpl( uint port_address );
+
+
+/**
+ * Writes and returns value to I/O port at port_address.
+ */
+nothrow ubyte outp( uint port_address, ubyte value );
+
+
+/**
+ * ditto
+ */
+nothrow ushort outpw( uint port_address, ushort value );
+
+
+/**
+ * ditto
+ */
+nothrow uint outpl( uint port_address, uint value );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/import/std/stdarg.di	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,32 @@
+/**
+ * These functions are built-in intrinsics to the compiler.
+ *
+ * Copyright: Public Domain
+ * License:   Public Domain
+ * Authors:   David Friedman
+ */
+module std.stdarg;
+
+version( GNU )
+{
+    private import gcc.builtins;
+    alias __builtin_va_list va_list;
+    alias __builtin_va_end  va_end;
+    alias __builtin_va_copy va_copy;
+}
+
+template va_start(T)
+{
+    void va_start( out va_list ap, inout T parmn )
+    {
+
+    }
+}
+
+template va_arg(T)
+{
+    T va_arg( inout va_list ap )
+    {
+        return T.init;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/build-dmd.bat	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,5 @@
+@echo off
+set OLDHOME=%HOME%
+set HOME=%CD%
+make clean all -fdmd-win32.mak
+set HOME=%OLDHOME%
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/build-dmd.sh	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+OLDHOME=$HOME
+export HOME=`pwd`
+
+goerror(){
+    export HOME=$OLDHOME
+    echo "="
+    echo "= *** Error ***"
+    echo "="
+    exit 1
+}
+
+make clean -fdmd-posix.mak          || goerror
+make -fdmd-posix.mak                || goerror
+chmod 644 ../import/core/*.di       || goerror
+chmod 644 ../import/core/sync/*.di  || goerror
+
+export HOME=$OLDHOME
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/build-ldc.sh	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+OLDHOME=$HOME
+export HOME=`pwd`
+
+goerror(){
+    export HOME=$OLDHOME
+    echo "="
+    echo "= *** Error ***"
+    echo "="
+    exit 1
+}
+
+make clean -fldc-posix.mak          || goerror
+make -fldc-posix.mak                || goerror
+chmod 644 ../import/core/*.di       || goerror
+chmod 644 ../import/core/sync/*.di  || goerror
+
+export HOME=$OLDHOME
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/bitmanip.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,286 @@
+/**
+ * This module contains a collection of bit-level operations.
+ *
+ * Copyright: Copyright (c) 2005-2008, The D Runtime Project
+ * License:   BSD Style, see LICENSE
+ * Authors:   Walter Bright, Don Clugston, Sean Kelly
+ */
+module core.bitmanip;
+
+
+version( DDoc )
+{
+    /**
+     * Scans the bits in v starting with bit 0, looking
+     * for the first set bit.
+     * Returns:
+     *  The bit number of the first bit set.
+     *  The return value is undefined if v is zero.
+     */
+    int bsf( uint v );
+
+
+    /**
+     * Scans the bits in v from the most significant bit
+     * to the least significant bit, looking
+     * for the first set bit.
+     * Returns:
+     *  The bit number of the first bit set.
+     *  The return value is undefined if v is zero.
+     * Example:
+     * ---
+     * import core.bitmanip;
+     *
+     * int main()
+     * {
+     *     uint v;
+     *     int x;
+     *
+     *     v = 0x21;
+     *     x = bsf(v);
+     *     printf("bsf(x%x) = %d\n", v, x);
+     *     x = bsr(v);
+     *     printf("bsr(x%x) = %d\n", v, x);
+     *     return 0;
+     * }
+     * ---
+     * Output:
+     *  bsf(x21) = 0<br>
+     *  bsr(x21) = 5
+     */
+    int bsr( uint v );
+
+
+    /**
+     * Tests the bit.
+     */
+    int bt( uint* p, uint bitnum );
+
+
+    /**
+     * Tests and complements the bit.
+     */
+    int btc( uint* p, uint bitnum );
+
+
+    /**
+     * Tests and resets (sets to 0) the bit.
+     */
+    int btr( uint* p, uint bitnum );
+
+
+    /**
+     * Tests and sets the bit.
+     * Params:
+     * p = a non-NULL pointer to an array of uints.
+     * index = a bit number, starting with bit 0 of p[0],
+     * and progressing. It addresses bits like the expression:
+    ---
+    p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)))
+    ---
+     * Returns:
+     *  A non-zero value if the bit was set, and a zero
+     *  if it was clear.
+     *
+     * Example:
+     * ---
+    import core.bitmanip;
+
+    int main()
+    {
+        uint array[2];
+
+        array[0] = 2;
+        array[1] = 0x100;
+
+        printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("bts(array, 35) = %d\n", <b>bts</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("btr(array, 35) = %d\n", <b>btr</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("bt(array, 1) = %d\n", <b>bt</b>(array, 1));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        return 0;
+    }
+     * ---
+     * Output:
+    <pre>
+    btc(array, 35) = 0
+    array = [0]:x2, [1]:x108
+    btc(array, 35) = -1
+    array = [0]:x2, [1]:x100
+    bts(array, 35) = 0
+    array = [0]:x2, [1]:x108
+    btr(array, 35) = -1
+    array = [0]:x2, [1]:x100
+    bt(array, 1) = -1
+    array = [0]:x2, [1]:x100
+    </pre>
+     */
+    int bts( uint* p, uint bitnum );
+
+
+    /**
+     * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes
+     * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3
+     * becomes byte 0.
+     */
+    uint bswap( uint v );
+
+
+    /**
+     * Reads I/O port at port_address.
+     */
+    ubyte inp( uint port_address );
+
+
+    /**
+     * ditto
+     */
+    ushort inpw( uint port_address );
+
+
+    /**
+     * ditto
+     */
+    uint inpl( uint port_address );
+
+
+    /**
+     * Writes and returns value to I/O port at port_address.
+     */
+    ubyte outp( uint port_address, ubyte value );
+
+
+    /**
+     * ditto
+     */
+    ushort outpw( uint port_address, ushort value );
+
+
+    /**
+     * ditto
+     */
+    uint outpl( uint port_address, uint value );
+}
+else
+{
+    public import std.intrinsic;
+}
+
+
+/**
+ *  Calculates the number of set bits in a 32-bit integer.
+ */
+int popcnt( uint x )
+{
+    // Avoid branches, and the potential for cache misses which
+    // could be incurred with a table lookup.
+
+    // We need to mask alternate bits to prevent the
+    // sum from overflowing.
+    // add neighbouring bits. Each bit is 0 or 1.
+    x = x - ((x>>1) & 0x5555_5555);
+    // now each two bits of x is a number 00,01 or 10.
+    // now add neighbouring pairs
+    x = ((x&0xCCCC_CCCC)>>2) + (x&0x3333_3333);
+    // now each nibble holds 0000-0100. Adding them won't
+    // overflow any more, so we don't need to mask any more
+
+    // Now add the nibbles, then the bytes, then the words
+    // We still need to mask to prevent double-counting.
+    // Note that if we used a rotate instead of a shift, we
+    // wouldn't need the masks, and could just divide the sum
+    // by 8 to account for the double-counting.
+    // On some CPUs, it may be faster to perform a multiply.
+
+    x += (x>>4);
+    x &= 0x0F0F_0F0F;
+    x += (x>>8);
+    x &= 0x00FF_00FF;
+    x += (x>>16);
+    x &= 0xFFFF;
+    return x;
+}
+
+
+debug( UnitTest )
+{
+    unittest
+    {
+      assert( popcnt( 0 ) == 0 );
+      assert( popcnt( 7 ) == 3 );
+      assert( popcnt( 0xAA )== 4 );
+      assert( popcnt( 0x8421_1248 ) == 8 );
+      assert( popcnt( 0xFFFF_FFFF ) == 32 );
+      assert( popcnt( 0xCCCC_CCCC ) == 16 );
+      assert( popcnt( 0x7777_7777 ) == 24 );
+    }
+}
+
+
+/**
+ * Reverses the order of bits in a 32-bit integer.
+ */
+uint bitswap( uint x )
+{
+
+    version( D_InlineAsm_X86 )
+    {
+        asm
+        {
+            // Author: Tiago Gasiba.
+            mov EDX, EAX;
+            shr EAX, 1;
+            and EDX, 0x5555_5555;
+            and EAX, 0x5555_5555;
+            shl EDX, 1;
+            or  EAX, EDX;
+            mov EDX, EAX;
+            shr EAX, 2;
+            and EDX, 0x3333_3333;
+            and EAX, 0x3333_3333;
+            shl EDX, 2;
+            or  EAX, EDX;
+            mov EDX, EAX;
+            shr EAX, 4;
+            and EDX, 0x0f0f_0f0f;
+            and EAX, 0x0f0f_0f0f;
+            shl EDX, 4;
+            or  EAX, EDX;
+            bswap EAX;
+        }
+    }
+    else
+    {
+        // swap odd and even bits
+        x = ((x >> 1) & 0x5555_5555) | ((x & 0x5555_5555) << 1);
+        // swap consecutive pairs
+        x = ((x >> 2) & 0x3333_3333) | ((x & 0x3333_3333) << 2);
+        // swap nibbles
+        x = ((x >> 4) & 0x0F0F_0F0F) | ((x & 0x0F0F_0F0F) << 4);
+        // swap bytes
+        x = ((x >> 8) & 0x00FF_00FF) | ((x & 0x00FF_00FF) << 8);
+        // swap 2-byte long pairs
+        x = ( x >> 16              ) | ( x               << 16);
+        return x;
+
+    }
+}
+
+
+debug( UnitTest )
+{
+    unittest
+    {
+        assert( bitswap( 0x8000_0100 ) == 0x0080_0001 );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/bitop.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,290 @@
+/**
+ * This module contains a collection of bit-level operations.
+ *
+ * Copyright: Copyright Don Clugston 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Don Clugston, Sean Kelly, Walter Bright
+ *
+ *          Copyright Don Clugston 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.bitop;
+
+
+version( D_Ddoc )
+{
+    /**
+     * Scans the bits in v starting with bit 0, looking
+     * for the first set bit.
+     * Returns:
+     *  The bit number of the first bit set.
+     *  The return value is undefined if v is zero.
+     */
+    int bsf( uint v );
+
+    /**
+     * Scans the bits in v from the most significant bit
+     * to the least significant bit, looking
+     * for the first set bit.
+     * Returns:
+     *  The bit number of the first bit set.
+     *  The return value is undefined if v is zero.
+     * Example:
+     * ---
+     * import core.bitop;
+     *
+     * int main()
+     * {
+     *     uint v;
+     *     int x;
+     *
+     *     v = 0x21;
+     *     x = bsf(v);
+     *     printf("bsf(x%x) = %d\n", v, x);
+     *     x = bsr(v);
+     *     printf("bsr(x%x) = %d\n", v, x);
+     *     return 0;
+     * }
+     * ---
+     * Output:
+     *  bsf(x21) = 0<br>
+     *  bsr(x21) = 5
+     */
+    int bsr( uint v );
+
+
+    /**
+     * Tests the bit.
+     */
+    int bt( uint* p, uint bitnum );
+
+
+    /**
+     * Tests and complements the bit.
+     */
+    int btc( uint* p, uint bitnum );
+
+
+    /**
+     * Tests and resets (sets to 0) the bit.
+     */
+    int btr( uint* p, uint bitnum );
+
+
+    /**
+     * Tests and sets the bit.
+     * Params:
+     * p = a non-NULL pointer to an array of uints.
+     * index = a bit number, starting with bit 0 of p[0],
+     * and progressing. It addresses bits like the expression:
+    ---
+    p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)))
+    ---
+     * Returns:
+     *  A non-zero value if the bit was set, and a zero
+     *  if it was clear.
+     *
+     * Example:
+     * ---
+    import core.bitop;
+
+    int main()
+    {
+        uint array[2];
+
+        array[0] = 2;
+        array[1] = 0x100;
+
+        printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("bts(array, 35) = %d\n", <b>bts</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("btr(array, 35) = %d\n", <b>btr</b>(array, 35));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        printf("bt(array, 1) = %d\n", <b>bt</b>(array, 1));
+        printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
+
+        return 0;
+    }
+     * ---
+     * Output:
+    <pre>
+    btc(array, 35) = 0
+    array = [0]:x2, [1]:x108
+    btc(array, 35) = -1
+    array = [0]:x2, [1]:x100
+    bts(array, 35) = 0
+    array = [0]:x2, [1]:x108
+    btr(array, 35) = -1
+    array = [0]:x2, [1]:x100
+    bt(array, 1) = -1
+    array = [0]:x2, [1]:x100
+    </pre>
+     */
+    int bts( uint* p, uint bitnum );
+
+
+    /**
+     * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes
+     * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3
+     * becomes byte 0.
+     */
+    uint bswap( uint v );
+
+
+    /**
+     * Reads I/O port at port_address.
+     */
+    ubyte inp( uint port_address );
+
+
+    /**
+     * ditto
+     */
+    ushort inpw( uint port_address );
+
+
+    /**
+     * ditto
+     */
+    uint inpl( uint port_address );
+
+
+    /**
+     * Writes and returns value to I/O port at port_address.
+     */
+    ubyte outp( uint port_address, ubyte value );
+
+
+    /**
+     * ditto
+     */
+    ushort outpw( uint port_address, ushort value );
+
+
+    /**
+     * ditto
+     */
+    uint outpl( uint port_address, uint value );
+}
+else
+{
+    public import std.intrinsic;
+}
+
+
+/**
+ *  Calculates the number of set bits in a 32-bit integer.
+ */
+int popcnt( uint x )
+{
+    // Avoid branches, and the potential for cache misses which
+    // could be incurred with a table lookup.
+
+    // We need to mask alternate bits to prevent the
+    // sum from overflowing.
+    // add neighbouring bits. Each bit is 0 or 1.
+    x = x - ((x>>1) & 0x5555_5555);
+    // now each two bits of x is a number 00,01 or 10.
+    // now add neighbouring pairs
+    x = ((x&0xCCCC_CCCC)>>2) + (x&0x3333_3333);
+    // now each nibble holds 0000-0100. Adding them won't
+    // overflow any more, so we don't need to mask any more
+
+    // Now add the nibbles, then the bytes, then the words
+    // We still need to mask to prevent double-counting.
+    // Note that if we used a rotate instead of a shift, we
+    // wouldn't need the masks, and could just divide the sum
+    // by 8 to account for the double-counting.
+    // On some CPUs, it may be faster to perform a multiply.
+
+    x += (x>>4);
+    x &= 0x0F0F_0F0F;
+    x += (x>>8);
+    x &= 0x00FF_00FF;
+    x += (x>>16);
+    x &= 0xFFFF;
+    return x;
+}
+
+
+debug( UnitTest )
+{
+    unittest
+    {
+      assert( popcnt( 0 ) == 0 );
+      assert( popcnt( 7 ) == 3 );
+      assert( popcnt( 0xAA )== 4 );
+      assert( popcnt( 0x8421_1248 ) == 8 );
+      assert( popcnt( 0xFFFF_FFFF ) == 32 );
+      assert( popcnt( 0xCCCC_CCCC ) == 16 );
+      assert( popcnt( 0x7777_7777 ) == 24 );
+    }
+}
+
+
+/**
+ * Reverses the order of bits in a 32-bit integer.
+ */
+uint bitswap( uint x )
+{
+
+    version( D_InlineAsm_X86 )
+    {
+        asm
+        {
+            // Author: Tiago Gasiba.
+            mov EDX, EAX;
+            shr EAX, 1;
+            and EDX, 0x5555_5555;
+            and EAX, 0x5555_5555;
+            shl EDX, 1;
+            or  EAX, EDX;
+            mov EDX, EAX;
+            shr EAX, 2;
+            and EDX, 0x3333_3333;
+            and EAX, 0x3333_3333;
+            shl EDX, 2;
+            or  EAX, EDX;
+            mov EDX, EAX;
+            shr EAX, 4;
+            and EDX, 0x0f0f_0f0f;
+            and EAX, 0x0f0f_0f0f;
+            shl EDX, 4;
+            or  EAX, EDX;
+            bswap EAX;
+        }
+    }
+    else
+    {
+        // swap odd and even bits
+        x = ((x >> 1) & 0x5555_5555) | ((x & 0x5555_5555) << 1);
+        // swap consecutive pairs
+        x = ((x >> 2) & 0x3333_3333) | ((x & 0x3333_3333) << 2);
+        // swap nibbles
+        x = ((x >> 4) & 0x0F0F_0F0F) | ((x & 0x0F0F_0F0F) << 4);
+        // swap bytes
+        x = ((x >> 8) & 0x00FF_00FF) | ((x & 0x00FF_00FF) << 8);
+        // swap 2-byte long pairs
+        x = ( x >> 16              ) | ( x               << 16);
+        return x;
+
+    }
+}
+
+
+debug( UnitTest )
+{
+    unittest
+    {
+        assert( bitswap( 0x8000_0100 ) == 0x0080_0001 );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/exception.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,279 @@
+/**
+ * The exception module defines all system-level exceptions and provides a
+ * mechanism to alter system-level error handling.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.exception;
+
+
+private
+{
+    alias void function( string file, size_t line, string msg = null ) assertHandlerType;
+
+    // Note that this is set on a per-thread basis (should it be global?)
+    assertHandlerType assertHandler   = null;
+}
+
+
+/**
+ * Thrown on a range error.
+ */
+class RangeError : Error
+{
+    this( string file, size_t line )
+    {
+        super( "Range violation", file, line );
+    }
+}
+
+
+/**
+ * Thrown on an assert error.
+ */
+class AssertError : Error
+{
+    this( string file, size_t line )
+    {
+        super( "Assertion failure", file, line );
+    }
+
+    this( string msg, string file, size_t line )
+    {
+        super( msg, file, line );
+    }
+}
+
+
+/**
+ * Thrown on finalize error.
+ */
+class FinalizeError : Error
+{
+    ClassInfo   info;
+
+    this( ClassInfo c, Exception e = null )
+    {
+        super( "Finalization error", e );
+        info = c;
+    }
+
+    override string toString()
+    {
+        return "An exception was thrown while finalizing an instance of class " ~ info.name;
+    }
+}
+
+
+/**
+ * Thrown on hidden function error.
+ */
+class HiddenFuncError : Error
+{
+    this( ClassInfo ci )
+    {
+        super( "Hidden method called for " ~ ci.name );
+    }
+}
+
+
+/**
+ * Thrown on an out of memory error.
+ */
+class OutOfMemoryError : Error
+{
+    this( string file, size_t line )
+    {
+        super( "Memory allocation failed", file, line );
+    }
+
+    override string toString()
+    {
+        return msg ? super.toString() : "Memory allocation failed";
+    }
+}
+
+
+/**
+ * Thrown on a switch error.
+ */
+class SwitchError : Error
+{
+    this( string file, size_t line )
+    {
+        super( "No appropriate switch clause found", file, line );
+    }
+}
+
+
+/**
+ * Thrown on a unicode conversion error.
+ */
+class UnicodeException : Exception
+{
+    size_t idx;
+
+    this( string msg, size_t idx )
+    {
+        super( msg );
+        this.idx = idx;
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Overrides
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Overrides the default assert hander with a user-supplied version.
+ *
+ * Params:
+ *  h = The new assert handler.  Set to null to use the default handler.
+ */
+void setAssertHandler( assertHandlerType h )
+{
+    assertHandler = h;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Overridable Callbacks
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * A callback for assert errors in D.  The user-supplied assert handler will
+ * be called if one has been supplied, otherwise an AssertError will be thrown.
+ *
+ * Params:
+ *  file = The name of the file that signaled this error.
+ *  line = The line number on which this error occurred.
+ */
+extern (C) void onAssertError( string file, size_t line )
+{
+    if( assertHandler is null )
+        throw new AssertError( file, line );
+    assertHandler( file, line );
+}
+
+
+/**
+ * A callback for assert errors in D.  The user-supplied assert handler will
+ * be called if one has been supplied, otherwise an AssertError will be thrown.
+ *
+ * Params:
+ *  file = The name of the file that signaled this error.
+ *  line = The line number on which this error occurred.
+ *  msg  = An error message supplied by the user.
+ */
+extern (C) void onAssertErrorMsg( string file, size_t line, string msg )
+{
+    if( assertHandler is null )
+        throw new AssertError( msg, file, line );
+    assertHandler( file, line, msg );
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Internal Error Callbacks
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * A callback for array bounds errors in D.  A RangeError will be thrown.
+ *
+ * Params:
+ *  file = The name of the file that signaled this error.
+ *  line = The line number on which this error occurred.
+ *
+ * Throws:
+ *  RangeError.
+ */
+extern (C) void onRangeError( string file, size_t line )
+{
+    throw new RangeError( file, line );
+}
+
+
+/**
+ * A callback for finalize errors in D.  A FinalizeError will be thrown.
+ *
+ * Params:
+ *  e = The exception thrown during finalization.
+ *
+ * Throws:
+ *  FinalizeError.
+ */
+extern (C) void onFinalizeError( ClassInfo info, Exception ex )
+{
+    throw new FinalizeError( info, ex );
+}
+
+
+/**
+ * A callback for hidden function errors in D.  A HiddenFuncError will be
+ * thrown.
+ *
+ * Throws:
+ *  HiddenFuncError.
+ */
+extern (C) void onHiddenFuncError( Object o )
+{
+    throw new HiddenFuncError( o.classinfo );
+}
+
+
+/**
+ * A callback for out of memory errors in D.  An OutOfMemoryError will be
+ * thrown.
+ *
+ * Throws:
+ *  OutOfMemoryError.
+ */
+extern (C) void onOutOfMemoryError()
+{
+    // NOTE: Since an out of memory condition exists, no allocation must occur
+    //       while generating this object.
+    throw cast(OutOfMemoryError) cast(void*) OutOfMemoryError.classinfo.init;
+}
+
+
+/**
+ * A callback for switch errors in D.  A SwitchError will be thrown.
+ *
+ * Params:
+ *  file = The name of the file that signaled this error.
+ *  line = The line number on which this error occurred.
+ *
+ * Throws:
+ *  SwitchError.
+ */
+extern (C) void onSwitchError( string file, size_t line )
+{
+    throw new SwitchError( file, line );
+}
+
+
+/**
+ * A callback for unicode errors in D.  A UnicodeException will be thrown.
+ *
+ * Params:
+ *  msg = Information about the error.
+ *  idx = String index where this error was detected.
+ *
+ * Throws:
+ *  UnicodeException.
+ */
+extern (C) void onUnicodeError( string msg, size_t idx )
+{
+    throw new UnicodeException( msg, idx );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/memory.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,452 @@
+/**
+ * The memory module provides an interface to the garbage collector and to
+ * any other OS or API-level memory management facilities.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.memory;
+
+
+private
+{
+    extern (C) void gc_init();
+    extern (C) void gc_term();
+
+    extern (C) void gc_enable();
+    extern (C) void gc_disable();
+    extern (C) void gc_collect();
+    extern (C) void gc_minimize();
+
+    extern (C) uint gc_getAttr( void* p );
+    extern (C) uint gc_setAttr( void* p, uint a );
+    extern (C) uint gc_clrAttr( void* p, uint a );
+
+    extern (C) void*  gc_malloc( size_t sz, uint ba = 0 );
+    extern (C) void*  gc_calloc( size_t sz, uint ba = 0 );
+    extern (C) void*  gc_realloc( void* p, size_t sz, uint ba = 0 );
+    extern (C) size_t gc_extend( void* p, size_t mx, size_t sz );
+    extern (C) size_t gc_reserve( size_t sz );
+    extern (C) void   gc_free( void* p );
+
+    extern (C) void*   gc_addrOf( void* p );
+    extern (C) size_t  gc_sizeOf( void* p );
+
+    struct BlkInfo_
+    {
+        void*  base;
+        size_t size;
+        uint   attr;
+    }
+
+    extern (C) BlkInfo_ gc_query( void* p );
+
+    extern (C) void gc_addRoot( void* p );
+    extern (C) void gc_addRange( void* p, size_t sz );
+
+    extern (C) void gc_removeRoot( void* p );
+    extern (C) void gc_removeRange( void* p );
+}
+
+
+/**
+ * This struct encapsulates all garbage collection functionality for the D
+ * programming language.
+ */
+struct GC
+{
+    /**
+     * Enables automatic garbage collection behavior if collections have
+     * previously been suspended by a call to disable.  This function is
+     * reentrant, and must be called once for every call to disable before
+     * automatic collections are enabled.
+     */
+    static void enable()
+    {
+        gc_enable();
+    }
+
+
+    /**
+     * Disables automatic garbage collections performed to minimize the
+     * process footprint.  Collections may continue to occur in instances
+     * where the implementation deems necessary for correct program behavior,
+     * such as during an out of memory condition.  This function is reentrant,
+     * but enable must be called once for each call to disable.
+     */
+    static void disable()
+    {
+        gc_disable();
+    }
+
+
+    /**
+     * Begins a full collection.  While the meaning of this may change based
+     * on the garbage collector implementation, typical behavior is to scan
+     * all stack segments for roots, mark accessible memory blocks as alive,
+     * and then to reclaim free space.  This action may need to suspend all
+     * running threads for at least part of the collection process.
+     */
+    static void collect()
+    {
+        gc_collect();
+    }
+
+    /**
+     * Indicates that the managed memory space be minimized by returning free
+     * physical memory to the operating system.  The amount of free memory
+     * returned depends on the allocator design and on program behavior.
+     */
+    static void minimize()
+    {
+        gc_minimize();
+    }
+
+
+    /**
+     * Elements for a bit field representing memory block attributes.  These
+     * are manipulated via the getAttr, setAttr, clrAttr functions.
+     */
+    enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001, /// Finalize the data in this block on collect.
+        NO_SCAN  = 0b0000_0010, /// Do not scan through this block on collect.
+        NO_MOVE  = 0b0000_0100  /// Do not move this memory block on collect.
+    }
+
+
+    /**
+     * Contains aggregate information about a block of managed memory.  The
+     * purpose of this struct is to support a more efficient query style in
+     * instances where detailed information is needed.
+     *
+     * base = A pointer to the base of the block in question.
+     * size = The size of the block, calculated from base.
+     * attr = Attribute bits set on the memory block.
+     */
+    alias BlkInfo_ BlkInfo;
+
+
+    /**
+     * Returns a bit field representing all block attributes set for the memory
+     * referenced by p.  If p references memory not originally allocated by
+     * this garbage collector, points to the interior of a memory block, or if
+     * p is null, zero will be returned.
+     *
+     * Params:
+     *  p = A pointer to the root of a valid memory block or to null.
+     *
+     * Returns:
+     *  A bit field containing any bits set for the memory block referenced by
+     *  p or zero on error.
+     */
+    static uint getAttr( void* p )
+    {
+        return gc_getAttr( p );
+    }
+
+
+    /**
+     * Sets the specified bits for the memory references by p.  If p references
+     * memory not originally allocated by this garbage collector, points to the
+     * interior of a memory block, or if p is null, no action will be
+     * performed.
+     *
+     * Params:
+     *  p = A pointer to the root of a valid memory block or to null.
+     *  a = A bit field containing any bits to set for this memory block.
+     *
+     *  The result of a call to getAttr after the specified bits have been
+     *  set.
+     */
+    static uint setAttr( void* p, uint a )
+    {
+        return gc_setAttr( p, a );
+    }
+
+
+    /**
+     * Clears the specified bits for the memory references by p.  If p
+     * references memory not originally allocated by this garbage collector,
+     * points to the interior of a memory block, or if p is null, no action
+     * will be performed.
+     *
+     * Params:
+     *  p = A pointer to the root of a valid memory block or to null.
+     *  a = A bit field containing any bits to clear for this memory block.
+     *
+     * Returns:
+     *  The result of a call to getAttr after the specified bits have been
+     *  cleared.
+     */
+    static uint clrAttr( void* p, uint a )
+    {
+        return gc_clrAttr( p, a );
+    }
+
+
+    /**
+     * Requests an aligned block of managed memory from the garbage collector.
+     * This memory may be deleted at will with a call to free, or it may be
+     * discarded and cleaned up automatically during a collection run.  If
+     * allocation fails, this function will call onOutOfMemory which is
+     * expected to throw an OutOfMemoryException.
+     *
+     * Params:
+     *  sz = The desired allocation size in bytes.
+     *  ba = A bitmask of the attributes to set on this block.
+     *
+     * Returns:
+     *  A reference to the allocated memory or null if insufficient memory
+     *  is available.
+     *
+     * Throws:
+     *  OutOfMemoryException on allocation failure.
+     */
+    static void* malloc( size_t sz, uint ba = 0 )
+    {
+        return gc_malloc( sz, ba );
+    }
+
+
+    /**
+     * Requests an aligned block of managed memory from the garbage collector,
+     * which is initialized with all bits set to zero.  This memory may be
+     * deleted at will with a call to free, or it may be discarded and cleaned
+     * up automatically during a collection run.  If allocation fails, this
+     * function will call onOutOfMemory which is expected to throw an
+     * OutOfMemoryException.
+     *
+     * Params:
+     *  sz = The desired allocation size in bytes.
+     *  ba = A bitmask of the attributes to set on this block.
+     *
+     * Returns:
+     *  A reference to the allocated memory or null if insufficient memory
+     *  is available.
+     *
+     * Throws:
+     *  OutOfMemoryException on allocation failure.
+     */
+    static void* calloc( size_t sz, uint ba = 0 )
+    {
+        return gc_calloc( sz, ba );
+    }
+
+
+    /**
+     * If sz is zero, the memory referenced by p will be deallocated as if
+     * by a call to free.  A new memory block of size sz will then be
+     * allocated as if by a call to malloc, or the implementation may instead
+     * resize the memory block in place.  The contents of the new memory block
+     * will be the same as the contents of the old memory block, up to the
+     * lesser of the new and old sizes.  Note that existing memory will only
+     * be freed by realloc if sz is equal to zero.  The garbage collector is
+     * otherwise expected to later reclaim the memory block if it is unused.
+     * If allocation fails, this function will call onOutOfMemory which is
+     * expected to throw an OutOfMemoryException.  If p references memory not
+     * originally allocated by this garbage collector, or if it points to the
+     * interior of a memory block, no action will be taken.  If ba is zero
+     * (the default) and p references the head of a valid, known memory block
+     * then any bits set on the current block will be set on the new block if a
+     * reallocation is required.  If ba is not zero and p references the head
+     * of a valid, known memory block then the bits in ba will replace those on
+     * the current memory block and will also be set on the new block if a
+     * reallocation is required.
+     *
+     * Params:
+     *  p  = A pointer to the root of a valid memory block or to null.
+     *  sz = The desired allocation size in bytes.
+     *  ba = A bitmask of the attributes to set on this block.
+     *
+     * Returns:
+     *  A reference to the allocated memory on success or null if sz is
+     *  zero.  On failure, the original value of p is returned.
+     *
+     * Throws:
+     *  OutOfMemoryException on allocation failure.
+     */
+    static void* realloc( void* p, size_t sz, uint ba = 0 )
+    {
+        return gc_realloc( p, sz, ba );
+    }
+
+
+    /**
+     * Requests that the managed memory block referenced by p be extended in
+     * place by at least mx bytes, with a desired extension of sz bytes.  If an
+     * extension of the required size is not possible, if p references memory
+     * not originally allocated by this garbage collector, or if p points to
+     * the interior of a memory block, no action will be taken.
+     *
+     * Params:
+     *  mx = The minimum extension size in bytes.
+     *  sz = The  desired extension size in bytes.
+     *
+     * Returns:
+     *  The size in bytes of the extended memory block referenced by p or zero
+     *  if no extension occurred.
+     */
+    static size_t extend( void* p, size_t mx, size_t sz )
+    {
+        return gc_extend( p, mx, sz );
+    }
+
+
+    /**
+     * Requests that at least sz bytes of memory be obtained from the operating
+     * system and marked as free.
+     *
+     * Params:
+     *  sz = The desired size in bytes.
+     *
+     * Returns:
+     *  The actual number of bytes reserved or zero on error.
+     */
+    static size_t reserve( size_t sz )
+    {
+        return gc_reserve( sz );
+    }
+
+
+    /**
+     * Deallocates the memory referenced by p.  If p is null, no action
+     * occurs.  If p references memory not originally allocated by this
+     * garbage collector, or if it points to the interior of a memory block,
+     * no action will be taken.  The block will not be finalized regardless
+     * of whether the FINALIZE attribute is set.  If finalization is desired,
+     * use delete instead.
+     *
+     * Params:
+     *  p = A pointer to the root of a valid memory block or to null.
+     */
+    static void free( void* p )
+    {
+        gc_free( p );
+    }
+
+
+    /**
+     * Returns the base address of the memory block containing p.  This value
+     * is useful to determine whether p is an interior pointer, and the result
+     * may be passed to routines such as sizeOf which may otherwise fail.  If p
+     * references memory not originally allocated by this garbage collector, if
+     * p is null, or if the garbage collector does not support this operation,
+     * null will be returned.
+     *
+     * Params:
+     *  p = A pointer to the root or the interior of a valid memory block or to
+     *      null.
+     *
+     * Returns:
+     *  The base address of the memory block referenced by p or null on error.
+     */
+    static void* addrOf( void* p )
+    {
+        return gc_addrOf( p );
+    }
+
+
+    /**
+     * Returns the true size of the memory block referenced by p.  This value
+     * represents the maximum number of bytes for which a call to realloc may
+     * resize the existing block in place.  If p references memory not
+     * originally allocated by this garbage collector, points to the interior
+     * of a memory block, or if p is null, zero will be returned.
+     *
+     * Params:
+     *  p = A pointer to the root of a valid memory block or to null.
+     *
+     * Returns:
+     *  The size in bytes of the memory block referenced by p or zero on error.
+     */
+    static size_t sizeOf( void* p )
+    {
+        return gc_sizeOf( p );
+    }
+
+
+    /**
+     * Returns aggregate information about the memory block containing p.  If p
+     * references memory not originally allocated by this garbage collector, if
+     * p is null, or if the garbage collector does not support this operation,
+     * BlkInfo.init will be returned.  Typically, support for this operation
+     * is dependent on support for addrOf.
+     *
+     * Params:
+     *  p = A pointer to the root or the interior of a valid memory block or to
+     *      null.
+     *
+     * Returns:
+     *  Information regarding the memory block referenced by p or BlkInfo.init
+     *  on error.
+     */
+    static BlkInfo query( void* p )
+    {
+        return gc_query( p );
+    }
+
+
+    /**
+     * Adds the memory address referenced by p to an internal list of roots to
+     * be scanned during a collection.  If p is null, no operation is
+     * performed.
+     *
+     * Params:
+     *  p = A pointer to a valid memory address or to null.
+     */
+    static void addRoot( void* p )
+    {
+        gc_addRoot( p );
+    }
+
+
+    /**
+     * Adds the memory block referenced by p and of size sz to an internal list
+     * of ranges to be scanned during a collection.  If p is null, no operation
+     * is performed.
+     *
+     * Params:
+     *  p  = A pointer to a valid memory address or to null.
+     *  sz = The size in bytes of the block to add.  If sz is zero then the
+     *       no operation will occur.  If p is null then sz must be zero.
+     */
+    static void addRange( void* p, size_t sz )
+    {
+        gc_addRange( p, sz );
+    }
+
+
+    /**
+     * Removes the memory block referenced by p from an internal list of roots
+     * to be scanned during a collection.  If p is null or does not represent
+     * a value previously passed to add(void*) then no operation is performed.
+     *
+     *  p  = A pointer to a valid memory address or to null.
+     */
+    static void removeRoot( void* p )
+    {
+        gc_removeRoot( p );
+    }
+
+
+    /**
+     * Removes the memory block referenced by p from an internal list of ranges
+     * to be scanned during a collection.  If p is null or does not represent
+     * a value previously passed to add(void*, size_t) then no operation is
+     * performed.
+     *
+     * Params:
+     *  p  = A pointer to a valid memory address or to null.
+     */
+    static void removeRange( void* p )
+    {
+        gc_removeRange( p );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/runtime.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,211 @@
+/**
+ * The runtime module exposes information specific to the D runtime code.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.runtime;
+
+
+private
+{
+    extern (C) bool rt_isHalting();
+
+    alias bool function() ModuleUnitTester;
+    alias bool function(Object) CollectHandler;
+    alias Exception.TraceInfo function( void* ptr = null ) TraceHandler;
+
+    extern (C) void rt_setCollectHandler( CollectHandler h );
+    extern (C) void rt_setTraceHandler( TraceHandler h );
+
+    alias void delegate( Throwable ) ExceptionHandler;
+    extern (C) bool rt_init( ExceptionHandler dg = null );
+    extern (C) bool rt_term( ExceptionHandler dg = null );
+
+    extern (C) void* rt_loadLibrary( in char[] name );
+    extern (C) bool  rt_unloadLibrary( void* ptr );
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Runtime
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This struct encapsulates all functionality related to the underlying runtime
+ * module for the calling context.
+ */
+struct Runtime
+{
+    /**
+     * Initializes the runtime.  This call is to be used in instances where the
+     * standard program initialization process is not executed.  This is most
+     * often in shared libraries or in libraries linked to a C program.
+     *
+     * Params:
+     *  dg = A delegate which will receive any exception thrown during the
+     *       initialization process or null if such exceptions should be
+     *       discarded.
+     *
+     * Returns:
+     *  true if initialization succeeds and false if initialization fails.
+     */
+    static bool initialize( ExceptionHandler dg = null )
+    {
+        return rt_init( dg );
+    }
+
+
+    /**
+     * Terminates the runtime.  This call is to be used in instances where the
+     * standard program termination process will not be not executed.  This is
+     * most often in shared libraries or in libraries linked to a C program.
+     *
+     * Params:
+     *  dg = A delegate which will receive any exception thrown during the
+     *       termination process or null if such exceptions should be
+     *       discarded.
+     *
+     * Returns:
+     *  true if termination succeeds and false if termination fails.
+     */
+    static bool terminate( ExceptionHandler dg = null )
+    {
+        return rt_term( dg );
+    }
+
+
+    /**
+     * Returns true if the runtime is halting.  Under normal circumstances,
+     * this will be set between the time that normal application code has
+     * exited and before module dtors are called.
+     *
+     * Returns:
+     *  true if the runtime is halting.
+     */
+    static bool isHalting()
+    {
+        return rt_isHalting();
+    }
+
+
+    /**
+     * Locates a dynamic library with the supplied library name and dynamically
+     * loads it into the caller's address space.  If the library contains a D
+     * runtime it will be integrated with the current runtime.
+     *
+     * Params:
+     *  name = The name of the dynamic library to load.
+     *
+     * Returns:
+     *  A reference to the library or null on error.
+     */
+    static void* loadLibrary( in char[] name )
+    {
+        return rt_loadLibrary( name );
+    }
+
+
+    /**
+     * Unloads the dynamic library referenced by p.  If this library contains a
+     * D runtime then any necessary finalization or cleanup of that runtime
+     * will be performed.
+     *
+     * Params:
+     *  p = A reference to the library to unload.
+     */
+    static bool unloadLibrary( void* p )
+    {
+        return rt_unloadLibrary( p );
+    }
+
+
+    /**
+     * Overrides the default trace mechanism with s user-supplied version.  A
+     * trace represents the context from which an exception was thrown, and the
+     * trace handler will be called when this occurs.  The pointer supplied to
+     * this routine indicates the base address from which tracing should occur.
+     * If the supplied pointer is null then the trace routine should determine
+     * an appropriate calling context from which to begin the trace.
+     *
+     * Params:
+     *  h = The new trace handler.  Set to null to use the default handler.
+     */
+    static void traceHandler( TraceHandler h )
+    {
+        rt_setTraceHandler( h );
+    }
+
+
+    /**
+     * Overrides the default collect hander with a user-supplied version.  This
+     * routine will be called for each resource object that is finalized in a
+     * non-deterministic manner--typically during a garbage collection cycle.
+     * If the supplied routine returns true then the object's dtor will called
+     * as normal, but if the routine returns false than the dtor will not be
+     * called.  The default behavior is for all object dtors to be called.
+     *
+     * Params:
+     *  h = The new collect handler.  Set to null to use the default handler.
+     */
+    static void collectHandler( CollectHandler h )
+    {
+        rt_setCollectHandler( h );
+    }
+
+
+    /**
+     * Overrides the default module unit tester with a user-supplied version.
+     * This routine will be called once on program initialization.  The return
+     * value of this routine indicates to the runtime whether the body of the
+     * program will be executed.
+     *
+     * Params:
+     *  h = The new unit tester.  Set to null to use the default unit tester.
+     */
+    static void moduleUnitTester( ModuleUnitTester h )
+    {
+        sm_moduleUnitTester = h;
+    }
+
+
+private:
+    // Unit tests should only be run in single-threaded
+    __gshared ModuleUnitTester sm_moduleUnitTester = null;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Overridable Callbacks
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This routine is called by the runtime to run module unit tests on startup.
+ * The user-supplied unit tester will be called if one has been supplied,
+ * otherwise all unit tests will be run in sequence.
+ *
+ * Returns:
+ *  true if execution should continue after testing is complete and false if
+ *  not.  Default behavior is to return true.
+ */
+extern (C) bool runModuleUnitTests()
+{
+    if( Runtime.sm_moduleUnitTester is null )
+    {
+        foreach( m; ModuleInfo )
+        {
+            if( m.unitTest )
+                m.unitTest();
+        }
+        return true;
+    }
+    return Runtime.sm_moduleUnitTester();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/stdc/errno.c	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,26 @@
+/**
+ * This file contains wrapper functions for macro-defined C rouines.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#include <errno.h>
+
+
+int getErrno()
+{
+    return errno;
+}
+
+
+int setErrno( int val )
+{
+    errno = val;
+    return val;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/sync/barrier.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,153 @@
+/**
+ * The barrier module provides a primitive for synchronizing the progress of
+ * a group of threads.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sync.barrier;
+
+
+public import core.sync.exception;
+private import core.sync.condition;
+private import core.sync.mutex;
+
+version( Win32 )
+{
+    private import core.sys.windows.windows;
+}
+else version( Posix )
+{
+    private import core.stdc.errno;
+    private import core.sys.posix.pthread;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Barrier
+//
+// void wait();
+////////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This class represents a barrier across which threads may only travel in
+ * groups of a specific size.
+ */
+class Barrier
+{
+    ////////////////////////////////////////////////////////////////////////////
+    // Initialization
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Initializes a barrier object which releases threads in groups of limit
+     * in size.
+     *
+     * Params:
+     *  limit = The number of waiting threads to release in unison.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    this( uint limit )
+    in
+    {
+        assert( limit > 0 );
+    }
+    body
+    {
+        m_lock  = new Mutex;
+        m_cond  = new Condition( m_lock );
+        m_group = 0;
+        m_limit = limit;
+        m_count = limit;
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // General Actions
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Wait for the pre-determined number of threads and then proceed.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    void wait()
+    {
+        synchronized( m_lock )
+        {
+            uint group = m_group;
+
+            if( --m_count == 0 )
+            {
+                m_group++;
+                m_count = m_limit;
+                m_cond.notifyAll();
+            }
+            while( group == m_group )
+                m_cond.wait();
+        }
+    }
+
+
+private:
+    Mutex       m_lock;
+    Condition   m_cond;
+    uint        m_group;
+    uint        m_limit;
+    uint        m_count;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Unit Tests
+////////////////////////////////////////////////////////////////////////////////
+
+
+version( unittest )
+{
+    private import core.thread;
+
+
+    unittest
+    {
+        int  numThreads = 10;
+        auto barrier    = new Barrier( numThreads );
+        auto synInfo    = new Object;
+        int  numReady   = 0;
+        int  numPassed  = 0;
+
+        void threadFn()
+        {
+            synchronized( synInfo )
+            {
+                ++numReady;
+            }
+            barrier.wait();
+            synchronized( synInfo )
+            {
+                ++numPassed;
+            }
+        }
+
+        auto group = new ThreadGroup;
+
+        for( int i = 0; i < numThreads; ++i )
+        {
+            group.create( &threadFn );
+        }
+        group.joinAll();
+        assert( numReady == numThreads && numPassed == numThreads );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/sync/condition.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,573 @@
+/**
+ * The condition module provides a primitive for synchronized condition
+ * checking.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sync.condition;
+
+
+public import core.sync.exception;
+public import core.sync.mutex;
+
+version( Win32 )
+{
+    private import core.sync.semaphore;
+    private import core.sys.windows.windows;
+}
+else version( Posix )
+{
+    private import core.sync.config;
+    private import core.stdc.errno;
+    private import core.sys.posix.pthread;
+    private import core.sys.posix.time;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Condition
+//
+// void wait();
+// void notify();
+// void notifyAll();
+////////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This class represents a condition variable as concieved by C.A.R. Hoare.  As
+ * per Mesa type monitors however, "signal" has been replaced with "notify" to
+ * indicate that control is not transferred to the waiter when a notification
+ * is sent.
+ */
+class Condition
+{
+    ////////////////////////////////////////////////////////////////////////////
+    // Initialization
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Initializes a condition object which is associated with the supplied
+     * mutex object.
+     *
+     * Params:
+     *  m = The mutex with which this condition will be associated.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    this( Mutex m )
+    {
+        version( Win32 )
+        {
+            m_blockLock = CreateSemaphoreA( null, 1, 1, null );
+            if( m_blockLock == m_blockLock.init )
+                throw new SyncException( "Unable to initialize condition" );
+            scope(failure) CloseHandle( m_blockLock );
+
+            m_blockQueue = CreateSemaphoreA( null, 0, int.max, null );
+            if( m_blockQueue == m_blockQueue.init )
+                throw new SyncException( "Unable to initialize condition" );
+            scope(failure) CloseHandle( m_blockQueue );
+
+            InitializeCriticalSection( &m_unblockLock );
+            m_assocMutex = m;
+        }
+        else version( Posix )
+        {
+            m_mutexAddr = m.handleAddr();
+
+            int rc = pthread_cond_init( &m_hndl, null );
+            if( rc )
+                throw new SyncException( "Unable to initialize condition" );
+        }
+    }
+
+
+    ~this()
+    {
+        version( Win32 )
+        {
+            BOOL rc = CloseHandle( m_blockLock );
+            assert( rc, "Unable to destroy condition" );
+            rc = CloseHandle( m_blockQueue );
+            assert( rc, "Unable to destroy condition" );
+            DeleteCriticalSection( &m_unblockLock );
+        }
+        else version( Posix )
+        {
+            int rc = pthread_cond_destroy( &m_hndl );
+            assert( !rc, "Unable to destroy condition" );
+        }
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // General Actions
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Wait until notified.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    void wait()
+    {
+        version( Win32 )
+        {
+            timedWait( INFINITE );
+        }
+        else version( Posix )
+        {
+            int rc = pthread_cond_wait( &m_hndl, m_mutexAddr );
+            if( rc )
+                throw new SyncException( "Unable to wait for condition" );
+        }
+    }
+
+
+    /**
+     * Suspends the calling thread until a notification occurs or until the
+     * supplied time period has elapsed.
+     *
+     * Params:
+     *  period = The time to wait, in 100 nanosecond intervals.  This value may
+     *           be adjusted to equal to the maximum wait period supported by
+     *           the target platform if it is too large.
+     *
+     * In:
+     *  period must be non-negative.
+     *
+     * Throws:
+     *  SyncException on error.
+     *
+     * Returns:
+     *  true if notified before the timeout and false if not.
+     */
+    bool wait( long period )
+    in
+    {
+        assert( period >= 0 );
+    }
+    body
+    {
+        version( Win32 )
+        {
+            enum : uint
+            {
+                TICKS_PER_MILLI = 10_000,
+                MAX_WAIT_MILLIS = uint.max - 1
+            }
+
+            period /= TICKS_PER_MILLI;
+            if( period > MAX_WAIT_MILLIS )
+                period = MAX_WAIT_MILLIS;
+            return timedWait( cast(uint) period );
+        }
+        else version( Posix )
+        {
+            timespec t = void;
+            mktspec( t, period );
+
+            int rc = pthread_cond_timedwait( &m_hndl, m_mutexAddr, &t );
+            if( !rc )
+                return true;
+            if( rc == ETIMEDOUT )
+                return false;
+            throw new SyncException( "Unable to wait for condition" );
+        }
+    }
+
+    /**
+     * Notifies one waiter.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    void notify()
+    {
+        version( Win32 )
+        {
+            notify( false );
+        }
+        else version( Posix )
+        {
+            int rc = pthread_cond_signal( &m_hndl );
+            if( rc )
+                throw new SyncException( "Unable to notify condition" );
+        }
+    }
+
+
+    /**
+     * Notifies all waiters.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    void notifyAll()
+    {
+        version( Win32 )
+        {
+            notify( true );
+        }
+        else version( Posix )
+        {
+            int rc = pthread_cond_broadcast( &m_hndl );
+            if( rc )
+                throw new SyncException( "Unable to notify condition" );
+        }
+    }
+
+
+private:
+    version( Win32 )
+    {
+        bool timedWait( DWORD timeout )
+        {
+            int   numSignalsLeft;
+            int   numWaitersGone;
+            DWORD rc;
+
+            rc = WaitForSingleObject( m_blockLock, INFINITE );
+            assert( rc == WAIT_OBJECT_0 );
+
+            m_numWaitersBlocked++;
+
+            rc = ReleaseSemaphore( m_blockLock, 1, null );
+            assert( rc );
+
+            m_assocMutex.unlock();
+            scope(failure) m_assocMutex.lock();
+
+            rc = WaitForSingleObject( m_blockQueue, timeout );
+            assert( rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT );
+            bool timedOut = (rc == WAIT_TIMEOUT);
+
+            EnterCriticalSection( &m_unblockLock );
+            scope(failure) LeaveCriticalSection( &m_unblockLock );
+
+            if( (numSignalsLeft = m_numWaitersToUnblock) != 0 )
+            {
+                if ( timedOut )
+                {
+                    // timeout (or canceled)
+                    if( m_numWaitersBlocked != 0 )
+                    {
+                        m_numWaitersBlocked--;
+                        // do not unblock next waiter below (already unblocked)
+                        numSignalsLeft = 0;
+                    }
+                    else
+                    {
+                        // spurious wakeup pending!!
+                        m_numWaitersGone = 1;
+                    }
+                }
+                if( --m_numWaitersToUnblock == 0 )
+                {
+                    if( m_numWaitersBlocked != 0 )
+                    {
+                        // open the gate
+                        rc = ReleaseSemaphore( m_blockLock, 1, null );
+                        assert( rc );
+                        // do not open the gate below again
+                        numSignalsLeft = 0;
+                    }
+                    else if( (numWaitersGone = m_numWaitersGone) != 0 )
+                    {
+                        m_numWaitersGone = 0;
+                    }
+                }
+            }
+            else if( ++m_numWaitersGone == int.max / 2 )
+            {
+                // timeout/canceled or spurious event :-)
+                rc = WaitForSingleObject( m_blockLock, INFINITE );
+                assert( rc == WAIT_OBJECT_0 );
+                // something is going on here - test of timeouts?
+                m_numWaitersBlocked -= m_numWaitersGone;
+                rc = ReleaseSemaphore( m_blockLock, 1, null );
+                assert( rc == WAIT_OBJECT_0 );
+                m_numWaitersGone = 0;
+            }
+
+            LeaveCriticalSection( &m_unblockLock );
+
+            if( numSignalsLeft == 1 )
+            {
+                // better now than spurious later (same as ResetEvent)
+                for( ; numWaitersGone > 0; --numWaitersGone )
+                {
+                    rc = WaitForSingleObject( m_blockQueue, INFINITE );
+                    assert( rc == WAIT_OBJECT_0 );
+                }
+                // open the gate
+                rc = ReleaseSemaphore( m_blockLock, 1, null );
+                assert( rc );
+            }
+            else if( numSignalsLeft != 0 )
+            {
+                // unblock next waiter
+                rc = ReleaseSemaphore( m_blockQueue, 1, null );
+                assert( rc );
+            }
+            m_assocMutex.lock();
+            return !timedOut;
+        }
+
+
+        void notify( bool all )
+        {
+            DWORD rc;
+
+            EnterCriticalSection( &m_unblockLock );
+            scope(failure) LeaveCriticalSection( &m_unblockLock );
+
+            if( m_numWaitersToUnblock != 0 )
+            {
+                if( m_numWaitersBlocked == 0 )
+                {
+                    LeaveCriticalSection( &m_unblockLock );
+                    return;
+                }
+                if( all )
+                {
+                    m_numWaitersToUnblock += m_numWaitersBlocked;
+                    m_numWaitersBlocked = 0;
+                }
+                else
+                {
+                    m_numWaitersToUnblock++;
+                    m_numWaitersBlocked--;
+                }
+                LeaveCriticalSection( &m_unblockLock );
+            }
+            else if( m_numWaitersBlocked > m_numWaitersGone )
+            {
+                rc = WaitForSingleObject( m_blockLock, INFINITE );
+                assert( rc == WAIT_OBJECT_0 );
+                if( 0 != m_numWaitersGone )
+                {
+                    m_numWaitersBlocked -= m_numWaitersGone;
+                    m_numWaitersGone = 0;
+                }
+                if( all )
+                {
+                    m_numWaitersToUnblock = m_numWaitersBlocked;
+                    m_numWaitersBlocked = 0;
+                }
+                else
+                {
+                    m_numWaitersToUnblock = 1;
+                    m_numWaitersBlocked--;
+                }
+                LeaveCriticalSection( &m_unblockLock );
+                rc = ReleaseSemaphore( m_blockQueue, 1, null );
+                assert( rc );
+            }
+            else
+            {
+                LeaveCriticalSection( &m_unblockLock );
+            }
+        }
+
+
+        // NOTE: This implementation uses Algorithm 8c as described here:
+        //       http://groups.google.com/group/comp.programming.threads/
+        //              browse_frm/thread/1692bdec8040ba40/e7a5f9d40e86503a
+        HANDLE              m_blockLock;    // auto-reset event (now semaphore)
+        HANDLE              m_blockQueue;   // auto-reset event (now semaphore)
+        Mutex               m_assocMutex;   // external mutex/CS
+        CRITICAL_SECTION    m_unblockLock;  // internal mutex/CS
+        int                 m_numWaitersGone        = 0;
+        int                 m_numWaitersBlocked     = 0;
+        int                 m_numWaitersToUnblock   = 0;
+    }
+    else version( Posix )
+    {
+        pthread_cond_t      m_hndl;
+        pthread_mutex_t*    m_mutexAddr;
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Unit Tests
+////////////////////////////////////////////////////////////////////////////////
+
+
+version( unittest )
+{
+    private import core.thread;
+    private import core.sync.mutex;
+    private import core.sync.semaphore;
+
+
+    void testNotify()
+    {
+        auto mutex      = new Mutex;
+        auto condReady  = new Condition( mutex );
+        auto semDone    = new Semaphore;
+        auto synLoop    = new Object;
+        int  numWaiters = 10;
+        int  numTries   = 10;
+        int  numReady   = 0;
+        int  numTotal   = 0;
+        int  numDone    = 0;
+        int  numPost    = 0;
+
+        void waiter()
+        {
+            for( int i = 0; i < numTries; ++i )
+            {
+                synchronized( mutex )
+                {
+                    while( numReady < 1 )
+                    {
+                        condReady.wait();
+                    }
+                    --numReady;
+                    ++numTotal;
+                }
+
+                synchronized( synLoop )
+                {
+                    ++numDone;
+                }
+                semDone.wait();
+            }
+        }
+
+        auto group = new ThreadGroup;
+
+        for( int i = 0; i < numWaiters; ++i )
+            group.create( &waiter );
+
+        for( int i = 0; i < numTries; ++i )
+        {
+            for( int j = 0; j < numWaiters; ++j )
+            {
+                synchronized( mutex )
+                {
+                    ++numReady;
+                    condReady.notify();
+                }
+            }
+            while( true )
+            {
+                synchronized( synLoop )
+                {
+                    if( numDone >= numWaiters )
+                        break;
+                }
+                Thread.yield();
+            }
+            for( int j = 0; j < numWaiters; ++j )
+            {
+                semDone.notify();
+            }
+        }
+
+        group.joinAll();
+        assert( numTotal == numWaiters * numTries );
+    }
+
+
+    void testNotifyAll()
+    {
+        auto mutex      = new Mutex;
+        auto condReady  = new Condition( mutex );
+        int  numWaiters = 10;
+        int  numReady   = 0;
+        int  numDone    = 0;
+        bool alert      = false;
+
+        void waiter()
+        {
+            synchronized( mutex )
+            {
+                ++numReady;
+                while( !alert )
+                    condReady.wait();
+                ++numDone;
+            }
+        }
+
+        auto group = new ThreadGroup;
+
+        for( int i = 0; i < numWaiters; ++i )
+            group.create( &waiter );
+
+        while( true )
+        {
+            synchronized( mutex )
+            {
+                if( numReady >= numWaiters )
+                {
+                    alert = true;
+                    condReady.notifyAll();
+                    break;
+                }
+            }
+            Thread.yield();
+        }
+        group.joinAll();
+        assert( numReady == numWaiters && numDone == numWaiters );
+    }
+
+
+    void testWaitTimeout()
+    {
+        auto mutex      = new Mutex;
+        auto condReady  = new Condition( mutex );
+        bool waiting    = false;
+        bool alertedOne = true;
+        bool alertedTwo = true;
+
+        void waiter()
+        {
+            synchronized( mutex )
+            {
+                waiting    = true;
+                alertedOne = condReady.wait( 10_000_000 ); // 1s
+                alertedTwo = condReady.wait( 10_000_000 ); // 1s
+            }
+        }
+
+        auto thread = new Thread( &waiter );
+        thread.start();
+
+        while( true )
+        {
+            synchronized( mutex )
+            {
+                if( waiting )
+                {
+                    condReady.notify();
+                    break;
+                }
+            }
+            Thread.yield();
+        }
+        thread.join();
+        assert( waiting && alertedOne && !alertedTwo );
+    }
+
+
+    unittest
+    {
+        testNotify();
+        testNotifyAll();
+        testWaitTimeout();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/sync/config.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,72 @@
+/**
+ * The config module contains utility routines and configuration information
+ * specific to this package.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sync.config;
+
+
+version( Posix )
+{
+    private import core.sys.posix.time;
+    private import core.sys.posix.sys.time;
+
+
+    void mktspec( inout timespec t, long delta = 0 )
+    {
+        static if( is( typeof( clock_gettime ) ) )
+        {
+            clock_gettime( CLOCK_REALTIME, &t );
+        }
+        else
+        {
+            timeval tv;
+
+            gettimeofday( &tv, null );
+            (cast(byte*) &t)[0 .. t.sizeof] = 0;
+            t.tv_sec  = cast(typeof(t.tv_sec))  tv.tv_sec;
+            t.tv_nsec = cast(typeof(t.tv_nsec)) tv.tv_usec * 1_000;
+        }
+        mvtspec( t, delta );
+    }
+
+
+    void mvtspec( inout timespec t, long delta )
+    {
+        if( delta == 0 )
+            return;
+
+        enum : uint
+        {
+            NANOS_PER_TICK   = 100,
+            TICKS_PER_SECOND = 10_000_000,
+            NANOS_PER_SECOND = NANOS_PER_TICK * TICKS_PER_SECOND,
+        }
+
+        if( t.tv_sec.max - t.tv_sec < delta / TICKS_PER_SECOND )
+        {
+            t.tv_sec  = t.tv_sec.max;
+            t.tv_nsec = 0;
+        }
+        else
+        {
+            t.tv_sec += cast(typeof(t.tv_sec)) (delta / TICKS_PER_SECOND);
+            long ns = (delta % TICKS_PER_SECOND) * NANOS_PER_TICK;
+            if( NANOS_PER_SECOND - t.tv_nsec > ns )
+            {
+                t.tv_nsec = cast(typeof(t.tv_nsec)) ns;
+                return;
+            }
+            t.tv_sec  += 1;
+            t.tv_nsec += cast(typeof(t.tv_nsec)) (ns - NANOS_PER_SECOND);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/sync/exception.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,26 @@
+/**
+ * The barrier module provides a primitive for synchronizing the progress of
+ * a group of threads.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sync.exception;
+
+
+/**
+ * Base class for synchronization exceptions.
+ */
+class SyncException : Exception
+{
+    this( string msg )
+    {
+        super( msg );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/sync/mutex.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,268 @@
+/**
+ * The mutex module provides a primitive for maintaining mutually exclusive
+ * access.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sync.mutex;
+
+
+public import core.sync.exception;
+
+version( Win32 )
+{
+    private import core.sys.windows.windows;
+}
+else version( Posix )
+{
+    private import core.sys.posix.pthread;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Mutex
+//
+// void lock();
+// void unlock();
+// bool tryLock();
+////////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This class represents a general purpose, recursive mutex.
+ */
+class Mutex :
+    Object.Monitor
+{
+    ////////////////////////////////////////////////////////////////////////////
+    // Initialization
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Initializes a mutex object.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    this()
+    {
+        version( Win32 )
+        {
+            InitializeCriticalSection( &m_hndl );
+        }
+        else version( Posix )
+        {
+            int rc = pthread_mutex_init( &m_hndl, &sm_attr );
+            if( rc )
+                throw new SyncException( "Unable to initialize mutex" );
+        }
+        m_proxy.link = this;
+        // NOTE: With DMD this can be "this.__monitor = &m_proxy".
+        (cast(void**) this)[1] = &m_proxy;
+    }
+
+
+    /**
+     * Initializes a mutex object and sets it as the monitor for o.
+     *
+     * In:
+     *  o must not already have a monitor.
+     */
+    this( Object o )
+    in
+    {
+        // NOTE: With DMD this can be "o.__monitor is null".
+        assert( (cast(void**) o)[1] is null );
+    }
+    body
+    {
+        this();
+        // NOTE: With DMD this can be "o.__monitor = &m_proxy".
+        (cast(void**) o)[1] = &m_proxy;
+    }
+
+
+    ~this()
+    {
+        version( Win32 )
+        {
+            DeleteCriticalSection( &m_hndl );
+        }
+        else version( Posix )
+        {
+            int rc = pthread_mutex_destroy( &m_hndl );
+            assert( !rc, "Unable to destroy mutex" );
+        }
+        (cast(void**) this)[1] = null;
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // General Actions
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * If this lock is not already held by the caller, the lock is acquired,
+     * then the internal counter is incremented by one.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    void lock()
+    {
+        version( Win32 )
+        {
+            EnterCriticalSection( &m_hndl );
+        }
+        else version( Posix )
+        {
+            int rc = pthread_mutex_lock( &m_hndl );
+            if( rc )
+                throw new SyncException( "Unable to lock mutex" );
+        }
+    }
+
+
+    /**
+     * Decrements the internal lock count by one.  If this brings the count to
+     * zero, the lock is released.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    void unlock()
+    {
+        version( Win32 )
+        {
+            LeaveCriticalSection( &m_hndl );
+        }
+        else version( Posix )
+        {
+            int rc = pthread_mutex_unlock( &m_hndl );
+            if( rc )
+                throw new SyncException( "Unable to unlock mutex" );
+        }
+    }
+
+
+    /**
+     * If the lock is held by another caller, the method returns.  Otherwise,
+     * the lock is acquired if it is not already held, and then the internal
+     * counter is incremented by one.
+     *
+     * Throws:
+     *  SyncException on error.
+     *
+     * Returns:
+     *  true if the lock was acquired and false if not.
+     */
+    bool tryLock()
+    {
+        version( Win32 )
+        {
+            return TryEnterCriticalSection( &m_hndl ) != 0;
+        }
+        else version( Posix )
+        {
+            return pthread_mutex_trylock( &m_hndl ) == 0;
+        }
+    }
+
+
+    version( Posix )
+    {
+        static this()
+        {
+            int rc = pthread_mutexattr_init( &sm_attr );
+            assert( !rc );
+
+            rc = pthread_mutexattr_settype( &sm_attr, PTHREAD_MUTEX_RECURSIVE );
+            assert( !rc );
+        }
+
+
+        static ~this()
+        {
+            int rc = pthread_mutexattr_destroy( &sm_attr );
+            assert( !rc );
+        }
+    }
+
+
+private:
+    version( Win32 )
+    {
+        CRITICAL_SECTION    m_hndl;
+    }
+    else version( Posix )
+    {
+        __gshared pthread_mutexattr_t  sm_attr;
+
+        pthread_mutex_t     m_hndl;
+    }
+
+    struct MonitorProxy
+    {
+        Object.Monitor link;
+    }
+
+    MonitorProxy            m_proxy;
+
+
+package:
+    version( Posix )
+    {
+        pthread_mutex_t* handleAddr()
+        {
+            return &m_hndl;
+        }
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Unit Tests
+////////////////////////////////////////////////////////////////////////////////
+
+
+version( unittest )
+{
+    private import core.thread;
+
+
+    unittest
+    {
+        auto mutex      = new Mutex;
+        int  numThreads = 10;
+        int  numTries   = 1000;
+        int  lockCount  = 0;
+
+        void testFn()
+        {
+            for( int i = 0; i < numTries; ++i )
+            {
+                synchronized( mutex )
+                {
+                    ++lockCount;
+                }
+            }
+        }
+
+        auto group = new ThreadGroup;
+
+        for( int i = 0; i < numThreads; ++i )
+            group.create( &testFn );
+
+        group.joinAll();
+        assert( lockCount == numThreads * numTries );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/sync/rwmutex.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,512 @@
+/**
+ * The read/write mutex module provides a primitive for maintaining shared read
+ * access and mutually exclusive write access.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sync.rwmutex;
+
+
+public import core.sync.exception;
+private import core.sync.condition;
+private import core.sync.mutex;
+
+version( Win32 )
+{
+    private import core.sys.windows.windows;
+}
+else version( Posix )
+{
+    private import core.sys.posix.pthread;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// ReadWriteMutex
+//
+// Reader reader();
+// Writer writer();
+////////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This class represents a mutex that allows any number of readers to enter,
+ * but when a writer enters, all other readers and writers are blocked.
+ *
+ * Please note that this mutex is not recursive and is intended to guard access
+ * to data only.  Also, no deadlock checking is in place because doing so would
+ * require dynamic memory allocation, which would reduce performance by an
+ * unacceptable amount.  As a result, any attempt to recursively acquire this
+ * mutex may well deadlock the caller, particularly if a write lock is acquired
+ * while holding a read lock, or vice-versa.  In practice, this should not be
+ * an issue however, because it is uncommon to call deeply into unknown code
+ * while holding a lock that simply protects data.
+ */
+class ReadWriteMutex
+{
+    /**
+     * Defines the policy used by this mutex.  Currently, two policies are
+     * defined.
+     *
+     * The first will queue writers until no readers hold the mutex, then
+     * pass the writers through one at a time.  If a reader acquires the mutex
+     * while there are still writers queued, the reader will take precedence.
+     *
+     * The second will queue readers if there are any writers queued.  Writers
+     * are passed through one at a time, and once there are no writers present,
+     * all queued readers will be alerted.
+     *
+     * Future policies may offer a more even balance between reader and writer
+     * precedence.
+     */
+    enum Policy
+    {
+        PREFER_READERS, /// Readers get preference.  This may starve writers.
+        PREFER_WRITERS  /// Writers get preference.  This may starve readers.
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Initialization
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Initializes a read/write mutex object with the supplied policy.
+     *
+     * Params:
+     *  policy = The policy to use.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    this( Policy policy = Policy.PREFER_WRITERS )
+    {
+        m_commonMutex = new Mutex;
+        if( !m_commonMutex )
+            throw new SyncException( "Unable to initialize mutex" );
+        scope(failure) delete m_commonMutex;
+
+        m_readerQueue = new Condition( m_commonMutex );
+        if( !m_readerQueue )
+            throw new SyncException( "Unable to initialize mutex" );
+        scope(failure) delete m_readerQueue;
+
+        m_writerQueue = new Condition( m_commonMutex );
+        if( !m_writerQueue )
+            throw new SyncException( "Unable to initialize mutex" );
+        scope(failure) delete m_writerQueue;
+
+        m_policy = policy;
+        m_reader = new Reader;
+        m_writer = new Writer;
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // General Properties
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Gets the policy for the associated mutex.
+     *
+     * Returns:
+     *  The policy used by this mutex.
+     */
+    Policy policy()
+    {
+        return m_policy;
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Reader/Writer Handles
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Gets an object representing the reader lock for the associated mutex.
+     *
+     * Returns:
+     *  A reader sub-mutex.
+     */
+    Reader reader()
+    {
+        return m_reader;
+    }
+
+
+    /**
+     * Gets an object representing the writer lock for the associated mutex.
+     *
+     * Returns:
+     *  A writer sub-mutex.
+     */
+    Writer writer()
+    {
+        return m_writer;
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Reader
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * This class can be considered a mutex in its own right, and is used to
+     * negotiate a read lock for the enclosing mutex.
+     */
+    class Reader :
+        Object.Monitor
+    {
+        /**
+         * Initializes a read/write mutex reader proxy object.
+         */
+        this()
+        {
+            m_proxy.link = this;
+            (cast(void**) this)[1] = &m_proxy;
+        }
+
+
+        /**
+         * Acquires a read lock on the enclosing mutex.
+         */
+        void lock()
+        {
+            synchronized( m_commonMutex )
+            {
+                ++m_numQueuedReaders;
+                scope(exit) --m_numQueuedReaders;
+
+                while( shouldQueueReader() )
+                    m_readerQueue.wait();
+                ++m_numActiveReaders;
+            }
+        }
+
+
+        /**
+         * Releases a read lock on the enclosing mutex.
+         */
+        void unlock()
+        {
+            synchronized( m_commonMutex )
+            {
+                if( --m_numActiveReaders < 1 )
+                {
+                    if( m_numQueuedWriters > 0 )
+                        m_writerQueue.notify();
+                }
+            }
+        }
+
+
+        /**
+         * Attempts to acquire a read lock on the enclosing mutex.  If one can
+         * be obtained without blocking, the lock is acquired and true is
+         * returned.  If not, the lock is not acquired and false is returned.
+         *
+         * Returns:
+         *  true if the lock was acquired and false if not.
+         */
+        bool tryLock()
+        {
+            synchronized( m_commonMutex )
+            {
+                if( shouldQueueReader() )
+                    return false;
+                ++m_numActiveReaders;
+                return true;
+            }
+        }
+
+
+    private:
+        bool shouldQueueReader()
+        {
+            if( m_numActiveWriters > 0 )
+                return true;
+
+            switch( m_policy )
+            {
+            case Policy.PREFER_WRITERS:
+                 return m_numQueuedWriters > 0;
+
+            case Policy.PREFER_READERS:
+            default:
+                 break;
+            }
+
+        return false;
+        }
+
+        struct MonitorProxy
+        {
+            Object.Monitor link;
+        }
+
+        MonitorProxy    m_proxy;
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Writer
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * This class can be considered a mutex in its own right, and is used to
+     * negotiate a write lock for the enclosing mutex.
+     */
+    class Writer :
+        Object.Monitor
+    {
+        /**
+         * Initializes a read/write mutex writer proxy object.
+         */
+        this()
+        {
+            m_proxy.link = this;
+            (cast(void**) this)[1] = &m_proxy;
+        }
+
+
+        /**
+         * Acquires a write lock on the enclosing mutex.
+         */
+        void lock()
+        {
+            synchronized( m_commonMutex )
+            {
+                ++m_numQueuedWriters;
+                scope(exit) --m_numQueuedWriters;
+
+                while( shouldQueueWriter() )
+                    m_writerQueue.wait();
+                ++m_numActiveWriters;
+            }
+        }
+
+
+        /**
+         * Releases a write lock on the enclosing mutex.
+         */
+        void unlock()
+        {
+            synchronized( m_commonMutex )
+            {
+                if( --m_numActiveWriters < 1 )
+                {
+                    switch( m_policy )
+                    {
+                    default:
+                    case Policy.PREFER_READERS:
+                        if( m_numQueuedReaders > 0 )
+                            m_readerQueue.notifyAll();
+                        else if( m_numQueuedWriters > 0 )
+                            m_writerQueue.notify();
+                        break;
+                    case Policy.PREFER_WRITERS:
+                        if( m_numQueuedWriters > 0 )
+                            m_writerQueue.notify();
+                        else if( m_numQueuedReaders > 0 )
+                            m_readerQueue.notifyAll();
+                    }
+                }
+            }
+        }
+
+
+        /**
+         * Attempts to acquire a write lock on the enclosing mutex.  If one can
+         * be obtained without blocking, the lock is acquired and true is
+         * returned.  If not, the lock is not acquired and false is returned.
+         *
+         * Returns:
+         *  true if the lock was acquired and false if not.
+         */
+        bool tryLock()
+        {
+            synchronized( m_commonMutex )
+            {
+                if( shouldQueueWriter() )
+                    return false;
+                ++m_numActiveWriters;
+                return true;
+            }
+        }
+
+
+    private:
+        bool shouldQueueWriter()
+        {
+            if( m_numActiveWriters > 0 ||
+                m_numActiveReaders > 0 )
+                return true;
+            switch( m_policy )
+            {
+            case Policy.PREFER_READERS:
+                return m_numQueuedReaders > 0;
+
+            case Policy.PREFER_WRITERS:
+            default:
+                 break;
+            }
+
+        return false;
+        }
+
+        struct MonitorProxy
+        {
+            Object.Monitor link;
+        }
+
+        MonitorProxy    m_proxy;
+    }
+
+
+private:
+    Policy      m_policy;
+    Reader      m_reader;
+    Writer      m_writer;
+
+    Mutex       m_commonMutex;
+    Condition   m_readerQueue;
+    Condition   m_writerQueue;
+
+    int         m_numQueuedReaders;
+    int         m_numActiveReaders;
+    int         m_numQueuedWriters;
+    int         m_numActiveWriters;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Unit Tests
+////////////////////////////////////////////////////////////////////////////////
+
+
+version( unittest )
+{
+    static if( !is( typeof( Thread ) ) )
+        private import core.thread;
+
+
+    void testRead( ReadWriteMutex.Policy policy )
+    {
+        auto mutex      = new ReadWriteMutex( policy );
+        auto synInfo    = new Object;
+        int  numThreads = 10;
+        int  numReaders = 0;
+        int  maxReaders = 0;
+
+        void readerFn()
+        {
+            synchronized( mutex.reader() )
+            {
+                synchronized( synInfo )
+                {
+                    if( ++numReaders > maxReaders )
+                        maxReaders = numReaders;
+                }
+                Thread.sleep( 100_000 ); // 1ms
+                synchronized( synInfo )
+                {
+                    --numReaders;
+                }
+            }
+        }
+
+        auto group = new ThreadGroup;
+
+        for( int i = 0; i < numThreads; ++i )
+        {
+            group.create( &readerFn );
+        }
+        group.joinAll();
+        assert( numReaders < 1 && maxReaders > 1 );
+    }
+
+
+    void testReadWrite( ReadWriteMutex.Policy policy )
+    {
+        auto mutex      = new ReadWriteMutex( policy );
+        auto synInfo    = new Object;
+        int  numThreads = 10;
+        int  numReaders = 0;
+        int  numWriters = 0;
+        int  maxReaders = 0;
+        int  maxWriters = 0;
+        int  numTries   = 20;
+
+        void readerFn()
+        {
+            for( int i = 0; i < numTries; ++i )
+            {
+                synchronized( mutex.reader() )
+                {
+                    synchronized( synInfo )
+                    {
+                        if( ++numReaders > maxReaders )
+                            maxReaders = numReaders;
+                    }
+                    Thread.sleep( 100_000 ); // 1ms
+                    synchronized( synInfo )
+                    {
+                        --numReaders;
+                    }
+                }
+            }
+        }
+
+        void writerFn()
+        {
+            for( int i = 0; i < numTries; ++i )
+            {
+                synchronized( mutex.writer() )
+                {
+                    synchronized( synInfo )
+                    {
+                        if( ++numWriters > maxWriters )
+                            maxWriters = numWriters;
+                    }
+                    Thread.sleep( 100_000 ); // 1ms
+                    synchronized( synInfo )
+                    {
+                        --numWriters;
+                    }
+                }
+            }
+        }
+
+        auto group = new ThreadGroup;
+
+        for( int i = 0; i < numThreads; ++i )
+        {
+            group.create( &readerFn );
+            group.create( &writerFn );
+        }
+        group.joinAll();
+        assert( numReaders < 1 && maxReaders > 1 &&
+                numWriters < 1 && maxWriters < 2 );
+    }
+
+
+    unittest
+    {
+        testRead( ReadWriteMutex.Policy.PREFER_READERS );
+        testRead( ReadWriteMutex.Policy.PREFER_WRITERS );
+        testReadWrite( ReadWriteMutex.Policy.PREFER_READERS );
+        testReadWrite( ReadWriteMutex.Policy.PREFER_WRITERS );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/sync/semaphore.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,506 @@
+/**
+ * The semaphore module provides a general use semaphore for synchronization.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sync.semaphore;
+
+
+public import core.sync.exception;
+
+version( Win32 )
+{
+    private import core.sys.windows.windows;
+}
+else version( OSX )
+{
+    private import core.sync.config;
+    private import core.stdc.errno;
+    private import core.sys.posix.time;
+    private import core.sys.osx.mach.semaphore;
+}
+else version( Posix )
+{
+    private import core.sync.config;
+    private import core.stdc.errno;
+    private import core.sys.posix.pthread;
+    private import core.sys.posix.semaphore;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Semaphore
+//
+// void wait();
+// void notify();
+// bool tryWait();
+////////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This class represents a general counting semaphore as concieved by Edsger
+ * Dijkstra.  As per Mesa type monitors however, "signal" has been replaced
+ * with "notify" to indicate that control is not transferred to the waiter when
+ * a notification is sent.
+ */
+class Semaphore
+{
+    ////////////////////////////////////////////////////////////////////////////
+    // Initialization
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Initializes a semaphore object with the specified initial count.
+     *
+     * Params:
+     *  count = The initial count for the semaphore.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    this( uint count = 0 )
+    {
+        version( Win32 )
+        {
+            m_hndl = CreateSemaphoreA( null, count, int.max, null );
+            if( m_hndl == m_hndl.init )
+                throw new SyncException( "Unable to create semaphore" );
+        }
+        else version( OSX )
+        {
+            auto rc = semaphore_create( mach_task_self(), &m_hndl, SYNC_POLICY_FIFO, count );
+            if( rc )
+                throw new SyncException( "Unable to create semaphore" );
+        }
+        else version( Posix )
+        {
+            int rc = sem_init( &m_hndl, 0, count );
+            if( rc )
+                throw new SyncException( "Unable to create semaphore" );
+        }
+    }
+
+
+    ~this()
+    {
+        version( Win32 )
+        {
+            BOOL rc = CloseHandle( m_hndl );
+            assert( rc, "Unable to destroy semaphore" );
+        }
+        else version( OSX )
+        {
+            auto rc = semaphore_destroy( mach_task_self(), m_hndl );
+            assert( !rc, "Unable to destroy semaphore" );
+        }
+        else version( Posix )
+        {
+            int rc = sem_destroy( &m_hndl );
+            assert( !rc, "Unable to destroy semaphore" );
+        }
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // General Actions
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Wait until the current count is above zero, then atomically decrement
+     * the count by one and return.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    void wait()
+    {
+        version( Win32 )
+        {
+            DWORD rc = WaitForSingleObject( m_hndl, INFINITE );
+            if( rc != WAIT_OBJECT_0 )
+                throw new SyncException( "Unable to wait for semaphore" );
+        }
+        else version( OSX )
+        {
+            while( true )
+            {
+                auto rc = semaphore_wait( m_hndl );
+                if( !rc )
+                    return;
+                if( rc == KERN_ABORTED && errno == EINTR )
+                    continue;
+                throw new SyncException( "Unable to wait for semaphore" );
+            }
+        }
+        else version( Posix )
+        {
+            while( true )
+            {
+                if( !sem_wait( &m_hndl ) )
+                    return;
+                if( errno != EINTR )
+                    throw new SyncException( "Unable to wait for semaphore" );
+            }
+        }
+    }
+
+
+    /**
+     * Suspends the calling thread until the current count moves above zero or
+     * until the supplied time period has elapsed.  If the count moves above
+     * zero in this interval, then atomically decrement the count by one and
+     * return true.  Otherwise, return false.
+     *
+     *
+     * Params:
+     *  period = The time to wait, in 100 nanosecond intervals.  This value may
+     *           be adjusted to equal to the maximum wait period supported by
+     *           the target platform if it is too large.
+     *
+     * In:
+     *  period must be non-negative.
+     *
+     * Throws:
+     *  SyncException on error.
+     *
+     * Returns:
+     *  true if notified before the timeout and false if not.
+     */
+    bool wait( long period )
+    in
+    {
+        assert( period >= 0 );
+    }
+    body
+    {
+        version( Win32 )
+        {
+            enum : uint
+            {
+                TICKS_PER_MILLI = 10_000,
+                MAX_WAIT_MILLIS = uint.max - 1
+            }
+
+            period /= TICKS_PER_MILLI;
+            if( period > MAX_WAIT_MILLIS )
+                period = MAX_WAIT_MILLIS;
+            switch( WaitForSingleObject( m_hndl, cast(uint) period ) )
+            {
+            case WAIT_OBJECT_0:
+                return true;
+            case WAIT_TIMEOUT:
+                return false;
+            default:
+                throw new SyncException( "Unable to wait for semaphore" );
+            }
+        }
+        else version( OSX )
+        {            
+            mach_timespec_t t = void;
+            (cast(byte*) &t)[0 .. t.sizeof] = 0;
+
+            if( period != 0 )
+            {
+                enum : uint
+                {
+                    NANOS_PER_TICK   = 100,
+                    TICKS_PER_SECOND = 10_000_000,
+                    NANOS_PER_SECOND = NANOS_PER_TICK * TICKS_PER_SECOND,
+                }
+
+                if( t.tv_sec.max - t.tv_sec < period / TICKS_PER_SECOND )
+                {
+                    t.tv_sec  = t.tv_sec.max;
+                    t.tv_nsec = 0;
+                }
+                else
+                {
+                    t.tv_sec += cast(typeof(t.tv_sec)) (period / TICKS_PER_SECOND);
+                    long ns = (period % TICKS_PER_SECOND) * NANOS_PER_TICK;
+                    if( NANOS_PER_SECOND - t.tv_nsec > ns )
+                        t.tv_nsec = cast(typeof(t.tv_nsec)) ns;
+                    else
+                    {
+                        t.tv_sec  += 1;
+                        t.tv_nsec += ns - NANOS_PER_SECOND;
+                    }
+                }
+            }
+            while( true )
+            {
+                auto rc = semaphore_timedwait( m_hndl, t );
+                if( !rc )
+                    return true;
+                if( rc == KERN_OPERATION_TIMED_OUT )
+                    return false;
+                if( rc != KERN_ABORTED || errno != EINTR )
+                    throw new SyncException( "Unable to wait for semaphore" );
+            }
+            // -w trip
+            return false;
+        }
+        else version( Posix )
+        {
+            timespec t = void;
+            mktspec( t, period );
+
+            while( true )
+            {
+                if( !sem_timedwait( &m_hndl, &t ) )
+                    return true;
+                if( errno == ETIMEDOUT )
+                    return false;
+                if( errno != EINTR )
+                    throw new SyncException( "Unable to wait for semaphore" );
+            }
+            // -w trip
+            return false;
+        }
+    }
+
+
+    /**
+     * Atomically increment the current count by one.  This will notify one
+     * waiter, if there are any in the queue.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    void notify()
+    {
+        version( Win32 )
+        {
+            if( !ReleaseSemaphore( m_hndl, 1, null ) )
+                throw new SyncException( "Unable to notify semaphore" );
+        }
+        else version( OSX )
+        {
+            auto rc = semaphore_signal( m_hndl );
+            if( rc )
+                throw new SyncException( "Unable to notify semaphore" );
+        }
+        else version( Posix )
+        {
+            int rc = sem_post( &m_hndl );
+            if( rc )
+                throw new SyncException( "Unable to notify semaphore" );
+        }
+    }
+
+
+    /**
+     * If the current count is equal to zero, return.  Otherwise, atomically
+     * decrement the count by one and return true.
+     *
+     * Throws:
+     *  SyncException on error.
+     *
+     * Returns:
+     *  true if the count was above zero and false if not.
+     */
+    bool tryWait()
+    {
+        version( Win32 )
+        {
+            switch( WaitForSingleObject( m_hndl, 0 ) )
+            {
+            case WAIT_OBJECT_0:
+                return true;
+            case WAIT_TIMEOUT:
+                return false;
+            default:
+                throw new SyncException( "Unable to wait for semaphore" );
+            }
+        }
+        else version( OSX )
+        {
+            return wait( 0 );
+        }
+        else version( Posix )
+        {
+            while( true )
+            {
+                if( !sem_trywait( &m_hndl ) )
+                    return true;
+                if( errno == EAGAIN )
+                    return false;
+                if( errno != EINTR )
+                    throw new SyncException( "Unable to wait for semaphore" );
+            }
+            // -w trip
+            return false;
+        }
+    }
+
+
+private:
+    version( Win32 )
+    {
+        HANDLE  m_hndl;
+    }
+    else version( OSX )
+    {
+        semaphore_t m_hndl;
+    }
+    else version( Posix )
+    {
+        sem_t   m_hndl;
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Unit Tests
+////////////////////////////////////////////////////////////////////////////////
+
+
+version( unittest )
+{
+    private import core.thread;
+
+
+    void testWait()
+    {
+        auto semaphore    = new Semaphore;
+        int  numToProduce = 10;
+        bool allProduced  = false;
+        auto synProduced  = new Object;
+        int  numConsumed  = 0;
+        auto synConsumed  = new Object;
+        int  numConsumers = 10;
+        int  numComplete  = 0;
+        auto synComplete  = new Object;
+
+        void consumer()
+        {
+            while( true )
+            {
+                semaphore.wait();
+
+                synchronized( synProduced )
+                {
+                    if( allProduced )
+                        break;
+                }
+
+                synchronized( synConsumed )
+                {
+                    ++numConsumed;
+                }
+            }
+
+            synchronized( synComplete )
+            {
+                ++numComplete;
+            }
+        }
+
+        void producer()
+        {
+            assert( !semaphore.tryWait() );
+
+            for( int i = 0; i < numToProduce; ++i )
+            {
+                semaphore.notify();
+                Thread.yield();
+            }
+            Thread.sleep( 10_000_000 ); // 1s
+            synchronized( synProduced )
+            {
+                allProduced = true;
+            }
+
+            for( int i = 0; i < numConsumers; ++i )
+            {
+                semaphore.notify();
+                Thread.yield();
+            }
+
+            for( int i = numConsumers * 10000; i > 0; --i )
+            {
+                synchronized( synComplete )
+                {
+                    if( numComplete == numConsumers )
+                        break;
+                }
+                Thread.yield();
+            }
+
+            synchronized( synComplete )
+            {
+                assert( numComplete == numConsumers );
+            }
+
+            synchronized( synConsumed )
+            {
+                assert( numConsumed == numToProduce );
+            }
+
+            assert( !semaphore.tryWait() );
+            semaphore.notify();
+            assert( semaphore.tryWait() );
+            assert( !semaphore.tryWait() );
+        }
+
+        auto group = new ThreadGroup;
+
+        for( int i = 0; i < numConsumers; ++i )
+            group.create( &consumer );
+        group.create( &producer );
+        group.joinAll();
+    }
+
+
+    void testWaitTimeout()
+    {
+        auto synReady   = new Object;
+        auto semReady   = new Semaphore;
+        bool waiting    = false;
+        bool alertedOne = true;
+        bool alertedTwo = true;
+
+        void waiter()
+        {
+            synchronized( synReady )
+            {
+                waiting    = true;
+            }
+            alertedOne = semReady.wait( 10_000_000 ); // 100ms
+            alertedTwo = semReady.wait( 10_000_000 ); // 100ms
+        }
+
+        auto thread = new Thread( &waiter );
+        thread.start();
+
+        while( true )
+        {
+            synchronized( synReady )
+            {
+                if( waiting )
+                {
+                    semReady.notify();
+                    break;
+                }
+            }
+            Thread.yield();
+        }
+        thread.join();
+        assert( waiting && alertedOne && !alertedTwo );
+    }
+
+
+    unittest
+    {
+        testWait();
+        testWaitTimeout();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/thread.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,3516 @@
+/**
+ * The thread module provides support for thread creation and management.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.thread;
+
+
+// this should be true for most architectures
+version = StackGrowsDown;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Thread and Fiber Exceptions
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Base class for thread exceptions.
+ */
+class ThreadException : Exception
+{
+    this( string msg )
+    {
+        super( msg );
+    }
+}
+
+
+/**
+ * Base class for fiber exceptions.
+ */
+class FiberException : Exception
+{
+    this( string msg )
+    {
+        super( msg );
+    }
+}
+
+
+private
+{
+    //
+    // exposed by compiler runtime
+    //
+    extern (C) void* rt_stackBottom();
+    extern (C) void* rt_stackTop();
+
+
+    void* getStackBottom()
+    {
+        return rt_stackBottom();
+    }
+
+
+    void* getStackTop()
+    {
+        version( D_InlineAsm_X86 )
+        {
+            asm
+            {
+                naked;
+                mov EAX, ESP;
+                ret;
+            }
+        }
+        else
+        {
+            return rt_stackTop();
+        }
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Thread Entry Point and Signal Handlers
+///////////////////////////////////////////////////////////////////////////////
+
+
+version( Windows )
+{
+    private
+    {
+        import core.stdc.stdint : uintptr_t; // for _beginthreadex decl below
+        import core.sys.windows.windows;
+
+        const DWORD TLS_OUT_OF_INDEXES  = 0xFFFFFFFF;
+
+        extern (Windows) alias uint function(void*) btex_fptr;
+        extern (C) uintptr_t _beginthreadex(void*, uint, btex_fptr, void*, uint, uint*);
+
+        version( DigitalMars )
+        {
+            // NOTE: The memory between the addresses of _tlsstart and _tlsend
+            //       is the storage for thread-local data in D 2.0.  Both of
+            //       these are defined in dm\src\win32\tlsseg.asm by DMC.
+            extern (C)
+            {
+                extern __thread int _tlsstart;
+                extern __thread int _tlsend;
+            }
+        }
+        else
+        {
+            __gshared int   _tlsstart;
+            alias _tlsstart _tlsend;
+        }
+
+
+        //
+        // entry point for Windows threads
+        //
+        extern (Windows) uint thread_entryPoint( void* arg )
+        {
+            Thread  obj = cast(Thread) arg;
+            assert( obj );
+            scope( exit ) Thread.remove( obj );
+
+            assert( obj.m_curr is &obj.m_main );
+            obj.m_main.bstack = getStackBottom();
+            obj.m_main.tstack = obj.m_main.bstack;
+            Thread.add( &obj.m_main );
+            Thread.setThis( obj );
+
+            void* pstart = cast(void*) &_tlsstart;
+            void* pend   = cast(void*) &_tlsend;
+            obj.m_tls = pstart[0 .. pend - pstart];
+
+            // NOTE: No GC allocations may occur until the stack pointers have
+            //       been set and Thread.getThis returns a valid reference to
+            //       this thread object (this latter condition is not strictly
+            //       necessary on Windows but it should be followed for the
+            //       sake of consistency).
+
+            // TODO: Consider putting an auto exception object here (using
+            //       alloca) forOutOfMemoryError plus something to track
+            //       whether an exception is in-flight?
+
+            try
+            {
+                obj.run();
+            }
+            catch( Object o )
+            {
+                obj.m_unhandled = o;
+            }
+            return 0;
+        }
+
+
+        //
+        // copy of the same-named function in phobos.std.thread--it uses the
+        // Windows naming convention to be consistent with GetCurrentThreadId
+        //
+        HANDLE GetCurrentThreadHandle()
+        {
+            const uint DUPLICATE_SAME_ACCESS = 0x00000002;
+
+            HANDLE curr = GetCurrentThread(),
+                   proc = GetCurrentProcess(),
+                   hndl;
+
+            DuplicateHandle( proc, curr, proc, &hndl, 0, TRUE, DUPLICATE_SAME_ACCESS );
+            return hndl;
+        }
+    }
+}
+else version( Posix )
+{
+    private
+    {
+        import core.sys.posix.semaphore;
+        import core.sys.posix.pthread;
+        import core.sys.posix.signal;
+        import core.sys.posix.time;
+        import core.stdc.errno;
+
+        extern (C) int getErrno();
+
+        version( OSX )
+        {
+            import core.sys.osx.mach.thread_act;
+            extern (C) mach_port_t pthread_mach_thread_np(pthread_t);
+        }
+
+        version( GNU )
+        {
+            import gcc.builtins;
+        }
+
+        version( DigitalMars )
+        {
+            version( linux )
+            {
+                extern (C)
+                {
+                    extern __thread int _tlsstart;
+                    extern __thread int _tlsend;
+                }
+            }
+            else
+            {
+                __gshared int   _tlsstart;
+                alias _tlsstart _tlsend;
+            }
+        }
+        else
+        {
+            __gshared int   _tlsstart;
+            alias _tlsstart _tlsend;
+        }
+
+
+        //
+        // entry point for POSIX threads
+        //
+        extern (C) void* thread_entryPoint( void* arg )
+        {
+            Thread  obj = cast(Thread) arg;
+            assert( obj );
+            scope( exit )
+            {
+                // NOTE: isRunning should be set to false after the thread is
+                //       removed or a double-removal could occur between this
+                //       function and thread_suspendAll.
+                Thread.remove( obj );
+                obj.m_isRunning = false;
+            }
+
+            static extern (C) void thread_cleanupHandler( void* arg )
+            {
+                Thread  obj = cast(Thread) arg;
+                assert( obj );
+
+                // NOTE: If the thread terminated abnormally, just set it as
+                //       not running and let thread_suspendAll remove it from
+                //       the thread list.  This is safer and is consistent
+                //       with the Windows thread code.
+                obj.m_isRunning = false;
+            }
+
+            // NOTE: Using void to skip the initialization here relies on
+            //       knowledge of how pthread_cleanup is implemented.  It may
+            //       not be appropriate for all platforms.  However, it does
+            //       avoid the need to link the pthread module.  If any
+            //       implementation actually requires default initialization
+            //       then pthread_cleanup should be restructured to maintain
+            //       the current lack of a link dependency.
+            version( linux )
+            {
+                pthread_cleanup cleanup = void;
+                cleanup.push( &thread_cleanupHandler, cast(void*) obj );
+            }
+            else version( OSX )
+            {
+                pthread_cleanup cleanup = void;
+                cleanup.push( &thread_cleanupHandler, cast(void*) obj );
+            }
+            else
+            {
+                pthread_cleanup_push( &thread_cleanupHandler, cast(void*) obj );
+            }
+
+            // NOTE: For some reason this does not always work for threads.
+            //obj.m_main.bstack = getStackBottom();
+            version( D_InlineAsm_X86 )
+            {
+                static void* getBasePtr()
+                {
+                    asm
+                    {
+                        naked;
+                        mov EAX, EBP;
+                        ret;
+                    }
+                }
+
+                obj.m_main.bstack = getBasePtr();
+            }
+            else version( StackGrowsDown )
+                obj.m_main.bstack = &obj + 1;
+            else
+                obj.m_main.bstack = &obj;
+            obj.m_main.tstack = obj.m_main.bstack;
+            assert( obj.m_curr == &obj.m_main );
+            Thread.add( &obj.m_main );
+            Thread.setThis( obj );
+
+            void* pstart = cast(void*) &_tlsstart;
+            void* pend   = cast(void*) &_tlsend;
+            obj.m_tls = pstart[0 .. pend - pstart];
+
+            // NOTE: No GC allocations may occur until the stack pointers have
+            //       been set and Thread.getThis returns a valid reference to
+            //       this thread object (this latter condition is not strictly
+            //       necessary on Windows but it should be followed for the
+            //       sake of consistency).
+
+            // TODO: Consider putting an auto exception object here (using
+            //       alloca) forOutOfMemoryError plus something to track
+            //       whether an exception is in-flight?
+
+            try
+            {
+                obj.run();
+            }
+            catch( Object o )
+            {
+                obj.m_unhandled = o;
+            }
+            return null;
+        }
+
+
+        //
+        // used to track the number of suspended threads
+        //
+        __gshared sem_t   suspendCount;
+
+
+        extern (C) void thread_suspendHandler( int sig )
+        in
+        {
+            assert( sig == SIGUSR1 );
+        }
+        body
+        {
+	    version( LDC)
+            {
+                version(X86)
+                {
+                    uint eax,ecx,edx,ebx,ebp,esi,edi;
+                    asm
+                    {
+                        mov eax[EBP], EAX      ;
+                        mov ecx[EBP], ECX      ;
+                        mov edx[EBP], EDX      ;
+                        mov ebx[EBP], EBX      ;
+                        mov ebp[EBP], EBP      ;
+                        mov esi[EBP], ESI      ;
+                        mov edi[EBP], EDI      ;
+                    }
+                }
+                else version (X86_64)
+                {
+                    ulong rax,rbx,rcx,rdx,rbp,rsi,rdi,rsp,r8,r9,r10,r11,r12,r13,r14,r15;
+                    asm
+                    {
+                        movq rax[RBP], RAX        ;
+                        movq rbx[RBP], RBX        ;
+                        movq rcx[RBP], RCX        ;
+                        movq rdx[RBP], RDX        ;
+                        movq rbp[RBP], RBP        ;
+                        movq rsi[RBP], RSI        ;
+                        movq rdi[RBP], RDI        ;
+                        movq rsp[RBP], RSP        ;
+                        movq  r8[RBP], R8         ;
+                        movq  r9[RBP], R9         ;
+                        movq r10[RBP], R10        ;
+                        movq r11[RBP], R11        ;
+                        movq r12[RBP], R12        ;
+                        movq r13[RBP], R13        ;
+                        movq r14[RBP], R14        ;
+                        movq r15[RBP], R15        ;
+                    }
+                }
+                else
+                {
+                    static assert( false, "Architecture not supported." );
+                }
+            } else version( D_InlineAsm_X86 )
+            {
+                asm
+                {
+                    pushad;
+                }
+            }
+            else version( GNU )
+            {
+                __builtin_unwind_init();
+            }
+            else
+            {
+                static assert( false, "Architecture not supported." );
+            }
+
+            // NOTE: Since registers are being pushed and popped from the
+            //       stack, any other stack data used by this function should
+            //       be gone before the stack cleanup code is called below.
+            {
+                Thread  obj = Thread.getThis();
+
+                // NOTE: The thread reference returned by getThis is set within
+                //       the thread startup code, so it is possible that this
+                //       handler may be called before the reference is set.  In
+                //       this case it is safe to simply suspend and not worry
+                //       about the stack pointers as the thread will not have
+                //       any references to GC-managed data.
+                if( obj && !obj.m_lock )
+                {
+                    obj.m_curr.tstack = getStackTop();
+                }
+
+                sigset_t    sigres = void;
+                int         status;
+
+                status = sigfillset( &sigres );
+                assert( status == 0 );
+
+                status = sigdelset( &sigres, SIGUSR2 );
+                assert( status == 0 );
+
+                status = sem_post( &suspendCount );
+                assert( status == 0 );
+
+                sigsuspend( &sigres );
+
+                if( obj && !obj.m_lock )
+                {
+                    obj.m_curr.tstack = obj.m_curr.bstack;
+                }
+            }
+	    version( LDC ){}
+	    else version( D_InlineAsm_X86 )
+            {
+                asm
+                {
+                    popad;
+                }
+            }
+            else version( GNU )
+            {
+                // registers will be popped automatically
+            }
+            else
+            {
+                static assert( false, "Architecture not supported." );
+            }
+        }
+
+
+        extern (C) void thread_resumeHandler( int sig )
+        in
+        {
+            assert( sig == SIGUSR2 );
+        }
+        body
+        {
+
+        }
+    }
+}
+else
+{
+    // NOTE: This is the only place threading versions are checked.  If a new
+    //       version is added, the module code will need to be searched for
+    //       places where version-specific code may be required.  This can be
+    //       easily accomlished by searching for 'Windows' or 'Posix'.
+    static assert( false, "Unknown threading implementation." );
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Thread
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This class encapsulates all threading functionality for the D
+ * programming language.  As thread manipulation is a required facility
+ * for garbage collection, all user threads should derive from this
+ * class, and instances of this class should never be explicitly deleted.
+ * A new thread may be created using either derivation or composition, as
+ * in the following example.
+ *
+ * Example:
+ * ----------------------------------------------------------------------------
+ *
+ * class DerivedThread : Thread
+ * {
+ *     this()
+ *     {
+ *         super( &run );
+ *     }
+ *
+ * private :
+ *     void run()
+ *     {
+ *         printf( "Derived thread running.\n" );
+ *     }
+ * }
+ *
+ * void threadFunc()
+ * {
+ *     printf( "Composed thread running.\n" );
+ * }
+ *
+ * // create instances of each type
+ * Thread derived = new DerivedThread();
+ * Thread composed = new Thread( &threadFunc );
+ *
+ * // start both threads
+ * derived.start();
+ * composed.start();
+ *
+ * ----------------------------------------------------------------------------
+ */
+class Thread
+{
+    ///////////////////////////////////////////////////////////////////////////
+    // Initialization
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Initializes a thread object which is associated with a static
+     * D function.
+     *
+     * Params:
+     *  fn = The thread function.
+     *  sz = The stack size for this thread.
+     *
+     * In:
+     *  fn must not be null.
+     */
+    this( void function() fn, size_t sz = 0 )
+    in
+    {
+        assert( fn );
+    }
+    body
+    {
+        m_fn   = fn;
+        m_sz   = sz;
+        m_call = Call.FN;
+        m_curr = &m_main;
+    }
+
+
+    /**
+     * Initializes a thread object which is associated with a dynamic
+     * D function.
+     *
+     * Params:
+     *  dg = The thread function.
+     *  sz = The stack size for this thread.
+     *
+     * In:
+     *  dg must not be null.
+     */
+    this( void delegate() dg, size_t sz = 0 )
+    in
+    {
+        assert( dg );
+    }
+    body
+    {
+        m_dg   = dg;
+        m_sz   = sz;
+        m_call = Call.DG;
+        m_curr = &m_main;
+    }
+
+
+    /**
+     * Cleans up any remaining resources used by this object.
+     */
+    ~this()
+    {
+        if( m_addr == m_addr.init )
+        {
+            return;
+        }
+
+        version( Windows )
+        {
+            m_addr = m_addr.init;
+            CloseHandle( m_hndl );
+            m_hndl = m_hndl.init;
+        }
+        else version( Posix )
+        {
+            pthread_detach( m_addr );
+            m_addr = m_addr.init;
+        }
+        version( OSX )
+        {
+            m_tmach = m_tmach.init;
+        }
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // General Actions
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Starts the thread and invokes the function or delegate passed upon
+     * construction.
+     *
+     * In:
+     *  This routine may only be called once per thread instance.
+     *
+     * Throws:
+     *  ThreadException if the thread fails to start.
+     */
+    final void start()
+    in
+    {
+        assert( !next && !prev );
+    }
+    body
+    {
+        auto wasThreaded  = multiThreadedFlag;
+        multiThreadedFlag = true;
+        scope( failure )
+        {
+            if( !wasThreaded )
+                multiThreadedFlag = false;
+        }
+
+        version( Windows ) {} else
+        version( Posix )
+        {
+            pthread_attr_t  attr;
+
+            if( pthread_attr_init( &attr ) )
+                throw new ThreadException( "Error initializing thread attributes" );
+            if( m_sz && pthread_attr_setstacksize( &attr, m_sz ) )
+                throw new ThreadException( "Error initializing thread stack size" );
+            if( pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ) )
+                throw new ThreadException( "Error setting thread joinable" );
+        }
+
+        // NOTE: This operation needs to be synchronized to avoid a race
+        //       condition with the GC.  Without this lock, the thread
+        //       could start and allocate memory before being added to
+        //       the global thread list, preventing it from being scanned
+        //       and causing memory to be collected that is still in use.
+        synchronized( slock )
+        {
+            version( Windows )
+            {
+                m_hndl = cast(HANDLE) _beginthreadex( null, m_sz, &thread_entryPoint, cast(void*) this, 0, &m_addr );
+                if( cast(size_t) m_hndl == 0 )
+                    throw new ThreadException( "Error creating thread" );
+            }
+            else version( Posix )
+            {
+                m_isRunning = true;
+                scope( failure ) m_isRunning = false;
+
+                if( pthread_create( &m_addr, &attr, &thread_entryPoint, cast(void*) this ) != 0 )
+                    throw new ThreadException( "Error creating thread" );
+            }
+            version( OSX )
+            {
+                m_tmach = pthread_mach_thread_np( m_addr );
+                if( m_tmach == m_tmach.init )
+                    throw new ThreadException( "Error creating thread" );
+            }
+            add( this );
+        }
+    }
+
+
+    /**
+     * Waits for this thread to complete.  If the thread terminated as the
+     * result of an unhandled exception, this exception will be rethrown.
+     *
+     * Params:
+     *  rethrow = Rethrow any unhandled exception which may have caused this
+     *            thread to terminate.
+     *
+     * Throws:
+     *  ThreadException if the operation fails.
+     *  Any exception not handled by the joined thread.
+     *
+     * Returns:
+     *  Any exception not handled by this thread if rethrow = false, null
+     *  otherwise.
+     */
+    final Object join( bool rethrow = true )
+    {
+        version( Windows )
+        {
+            if( WaitForSingleObject( m_hndl, INFINITE ) != WAIT_OBJECT_0 )
+                throw new ThreadException( "Unable to join thread" );
+            // NOTE: m_addr must be cleared before m_hndl is closed to avoid
+            //       a race condition with isRunning.  The operation is labeled
+            //       volatile to prevent compiler reordering.
+            volatile m_addr = m_addr.init;
+            CloseHandle( m_hndl );
+            m_hndl = m_hndl.init;
+        }
+        else version( Posix )
+        {
+            if( pthread_join( m_addr, null ) != 0 )
+                throw new ThreadException( "Unable to join thread" );
+            // NOTE: pthread_join acts as a substitute for pthread_detach,
+            //       which is normally called by the dtor.  Setting m_addr
+            //       to zero ensures that pthread_detach will not be called
+            //       on object destruction.
+            volatile m_addr = m_addr.init;
+        }
+        if( m_unhandled )
+        {
+            if( rethrow )
+                throw m_unhandled;
+            return m_unhandled;
+        }
+        return null;
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // General Properties
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Gets the user-readable label for this thread.
+     *
+     * Returns:
+     *  The name of this thread.
+     */
+    final char[] name()
+    {
+        synchronized( this )
+        {
+            return m_name;
+        }
+    }
+
+
+    /**
+     * Sets the user-readable label for this thread.
+     *
+     * Params:
+     *  val = The new name of this thread.
+     */
+    final void name( char[] val )
+    {
+        synchronized( this )
+        {
+            m_name = val.dup;
+        }
+    }
+
+
+    /**
+     * Gets the daemon status for this thread.  While the runtime will wait for
+     * all normal threads to complete before tearing down the process, daemon
+     * threads are effectively ignored and thus will not prevent the process
+     * from terminating.  In effect, daemon threads will be terminated
+     * automatically by the OS when the process exits.
+     *
+     * Returns:
+     *  true if this is a daemon thread.
+     */
+    final bool isDaemon()
+    {
+        synchronized( this )
+        {
+            return m_isDaemon;
+        }
+    }
+
+
+    /**
+     * Sets the daemon status for this thread.  While the runtime will wait for
+     * all normal threads to complete before tearing down the process, daemon
+     * threads are effectively ignored and thus will not prevent the process
+     * from terminating.  In effect, daemon threads will be terminated
+     * automatically by the OS when the process exits.
+     *
+     * Params:
+     *  val = The new daemon status for this thread.
+     */
+    final void isDaemon( bool val )
+    {
+        synchronized( this )
+        {
+            m_isDaemon = val;
+        }
+    }
+
+
+    /**
+     * Tests whether this thread is running.
+     *
+     * Returns:
+     *  true if the thread is running, false if not.
+     */
+    final bool isRunning()
+    {
+        if( m_addr == m_addr.init )
+        {
+            return false;
+        }
+
+        version( Windows )
+        {
+            uint ecode = 0;
+            GetExitCodeThread( m_hndl, &ecode );
+            return ecode == STILL_ACTIVE;
+        }
+        else version( Posix )
+        {
+            // NOTE: It should be safe to access this value without
+            //       memory barriers because word-tearing and such
+            //       really isn't an issue for boolean values.
+            return m_isRunning;
+        }
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Thread Priority Actions
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * The minimum scheduling priority that may be set for a thread.  On
+     * systems where multiple scheduling policies are defined, this value
+     * represents the minimum valid priority for the scheduling policy of
+     * the process.
+     */
+    static const int PRIORITY_MIN;
+
+
+    /**
+     * The maximum scheduling priority that may be set for a thread.  On
+     * systems where multiple scheduling policies are defined, this value
+     * represents the minimum valid priority for the scheduling policy of
+     * the process.
+     */
+    static const int PRIORITY_MAX;
+
+
+    /**
+     * Gets the scheduling priority for the associated thread.
+     *
+     * Returns:
+     *  The scheduling priority of this thread.
+     */
+    final int priority()
+    {
+        version( Windows )
+        {
+            return GetThreadPriority( m_hndl );
+        }
+        else version( Posix )
+        {
+            int         policy;
+            sched_param param;
+
+            if( pthread_getschedparam( m_addr, &policy, &param ) )
+                throw new ThreadException( "Unable to get thread priority" );
+            return param.sched_priority;
+        }
+    }
+
+
+    /**
+     * Sets the scheduling priority for the associated thread.
+     *
+     * Params:
+     *  val = The new scheduling priority of this thread.
+     */
+    final void priority( int val )
+    {
+        version( Windows )
+        {
+            if( !SetThreadPriority( m_hndl, val ) )
+                throw new ThreadException( "Unable to set thread priority" );
+        }
+        else version( Posix )
+        {
+            // NOTE: pthread_setschedprio is not implemented on linux, so use
+            //       the more complicated get/set sequence below.
+            //if( pthread_setschedprio( m_addr, val ) )
+            //    throw new ThreadException( "Unable to set thread priority" );
+
+            int         policy;
+            sched_param param;
+
+            if( pthread_getschedparam( m_addr, &policy, &param ) )
+                throw new ThreadException( "Unable to set thread priority" );
+            param.sched_priority = val;
+            if( pthread_setschedparam( m_addr, policy, &param ) )
+                throw new ThreadException( "Unable to set thread priority" );
+        }
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Actions on Calling Thread
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Suspends the calling thread for at least the supplied period.  This may
+     * result in multiple OS calls if period is greater than the maximum sleep
+     * duration supported by the operating system.
+     *
+     * Params:
+     *  period = The minimum duration the calling thread should be suspended,
+     *           in 100 nanosecond intervals.
+     *
+     * In:
+     *  period must be non-negative.
+     *
+     * Example:
+     * ------------------------------------------------------------------------
+     *
+     * Thread.sleep( 500_000 );    // sleep for 50 milliseconds
+     * Thread.sleep( 50_000_000 ); // sleep for 5 seconds
+     *
+     * ------------------------------------------------------------------------
+     */
+    static void sleep( long period )
+    in
+    {
+        assert( period >= 0 );
+    }
+    body
+    {
+        version( Windows )
+        {
+            enum : uint
+            {
+                TICKS_PER_MILLI  = 10_000,
+                MAX_SLEEP_MILLIS = uint.max - 1
+            }
+
+            // NOTE: In instances where all other threads in the process have a
+            //       lower priority than the current thread, the current thread
+            //       will not yield with a sleep time of zero.  However, unlike
+            //       yield(), the user is not asking for a yield to occur but
+            //       only for execution to suspend for the requested interval.
+            //       Therefore, expected performance may not be met if a yield
+            //       is forced upon the user.
+            period /= TICKS_PER_MILLI;
+            while( period > MAX_SLEEP_MILLIS )
+            {
+                Sleep( MAX_SLEEP_MILLIS );
+                period -= MAX_SLEEP_MILLIS;
+            }
+            Sleep( cast(uint) period );
+        }
+        else version( Posix )
+        {
+            timespec tin  = void;
+            timespec tout = void;
+
+            enum : uint
+            {
+                NANOS_PER_TICK   = 100,
+                TICKS_PER_SECOND = 10_000_000,
+            }
+            enum : typeof(period)
+            {
+                MAX_SLEEP_TICKS = cast(typeof(period)) tin.tv_sec.max * TICKS_PER_SECOND
+            }
+
+            do
+            {
+                if( period > MAX_SLEEP_TICKS )
+                {
+                    tin.tv_sec = tin.tv_sec.max;
+                    tin.tv_nsec = 0;
+                }
+                else
+                {
+                    tin.tv_sec = cast(typeof(tin.tv_sec)) (period / TICKS_PER_SECOND);
+                    tin.tv_nsec = cast(typeof(tin.tv_nsec)) (period % TICKS_PER_SECOND) * NANOS_PER_TICK;
+                }
+                while( true )
+                {
+                    if( !nanosleep( &tin, &tout ) )
+                        return;
+                    if( getErrno() != EINTR )
+                        throw new ThreadException( "Unable to sleep for the specified duration" );
+                    tin = tout;
+                }
+                period -= (cast(typeof(period)) tin.tv_sec) * TICKS_PER_SECOND;
+                period -= (cast(typeof(period)) tin.tv_nsec) / NANOS_PER_TICK;
+            } while( period > 0 );
+        }
+    }
+
+
+    /**
+     * Forces a context switch to occur away from the calling thread.
+     */
+    static void yield()
+    {
+        version( Windows )
+        {
+            // NOTE: Sleep(1) is necessary because Sleep(0) does not give
+            //       lower priority threads any timeslice, so looping on
+            //       Sleep(0) could be resource-intensive in some cases.
+            Sleep( 1 );
+        }
+        else version( Posix )
+        {
+            sched_yield();
+        }
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Thread Accessors
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Provides a reference to the calling thread.
+     *
+     * Returns:
+     *  The thread object representing the calling thread.  The result of
+     *  deleting this object is undefined.
+     */
+    static Thread getThis()
+    {
+        // NOTE: This function may not be called until thread_init has
+        //       completed.  See thread_suspendAll for more information
+        //       on why this might occur.
+        version( Windows )
+        {
+            return cast(Thread) TlsGetValue( sm_this );
+        }
+        else version( Posix )
+        {
+            return cast(Thread) pthread_getspecific( sm_this );
+        }
+    }
+
+
+    /**
+     * Provides a list of all threads currently being tracked by the system.
+     *
+     * Returns:
+     *  An array containing references to all threads currently being
+     *  tracked by the system.  The result of deleting any contained
+     *  objects is undefined.
+     */
+    static Thread[] getAll()
+    {
+        synchronized( slock )
+        {
+            size_t   pos = 0;
+            Thread[] buf = new Thread[sm_tlen];
+
+            foreach( Thread t; Thread )
+            {
+                buf[pos++] = t;
+            }
+            return buf;
+        }
+    }
+
+
+    /**
+     * Operates on all threads currently being tracked by the system.  The
+     * result of deleting any Thread object is undefined.
+     *
+     * Params:
+     *  dg = The supplied code as a delegate.
+     *
+     * Returns:
+     *  Zero if all elemented are visited, nonzero if not.
+     */
+    static int opApply( int delegate( inout Thread ) dg )
+    {
+        synchronized( slock )
+        {
+            int ret = 0;
+
+            for( Thread t = sm_tbeg; t; t = t.next )
+            {
+                ret = dg( t );
+                if( ret )
+                    break;
+            }
+            return ret;
+        }
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Local Storage Actions
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Indicates the number of local storage pointers available at program
+     * startup.  It is recommended that this number be at least 64.
+     */
+    static const uint LOCAL_MAX = 64;
+
+
+    /**
+     * Reserves a local storage pointer for use and initializes this location
+     * to null for all running threads.
+     *
+     * Returns:
+     *  A key representing the array offset of this memory location.
+     */
+    static uint createLocal()
+    {
+        synchronized( slock )
+        {
+            foreach( uint key, inout bool set; sm_local )
+            {
+                if( !set )
+                {
+                    //foreach( Thread t; sm_tbeg ) Bug in GDC 0.24 SVN (r139)
+                    for( Thread t = sm_tbeg; t; t = t.next )
+                    {
+                        t.m_local[key] = null;
+                    }
+                    set = true;
+                    return key;
+                }
+            }
+            throw new ThreadException( "No more local storage slots available" );
+        }
+    }
+
+
+    /**
+     * Marks the supplied key as available and sets the associated location
+     * to null for all running threads.  It is assumed that any key passed
+     * to this function is valid.  The result of calling this function for
+     * a key which is still in use is undefined.
+     *
+     * Params:
+     *  key = The key to delete.
+     */
+    static void deleteLocal( uint key )
+    {
+        synchronized( slock )
+        {
+            sm_local[key] = false;
+            // foreach( Thread t; sm_tbeg ) Bug in GDC 0.24 SVN (r139)
+            for( Thread t = sm_tbeg; t; t = t.next )
+            {
+                t.m_local[key] = null;
+            }
+        }
+    }
+
+
+    /**
+     * Loads the value stored at key within a thread-local static array.  It is
+     * assumed that any key passed to this function is valid.
+     *
+     * Params:
+     *  key = The location which holds the desired data.
+     *
+     * Returns:
+     *  The data associated with the supplied key.
+     */
+    static void* getLocal( uint key )
+    {
+        return getThis().m_local[key];
+    }
+
+
+    /**
+     * Stores the supplied value at key within a thread-local static array.  It
+     * is assumed that any key passed to this function is valid.
+     *
+     * Params:
+     *  key = The location to store the supplied data.
+     *  val = The data to store.
+     *
+     * Returns:
+     *  A copy of the data which has just been stored.
+     */
+    static void* setLocal( uint key, void* val )
+    {
+        return getThis().m_local[key] = val;
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Static Initalizer
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * This initializer is used to set thread constants.  All functional
+     * initialization occurs within thread_init().
+     */
+    static this()
+    {
+        version( Windows )
+        {
+            PRIORITY_MIN = -15;
+            PRIORITY_MAX =  15;
+        }
+        else version( Posix )
+        {
+            int         policy;
+            sched_param param;
+            pthread_t   self = pthread_self();
+
+            int status = pthread_getschedparam( self, &policy, &param );
+            assert( status == 0 );
+
+            PRIORITY_MIN = sched_get_priority_min( policy );
+            assert( PRIORITY_MIN != -1 );
+
+            PRIORITY_MAX = sched_get_priority_max( policy );
+            assert( PRIORITY_MAX != -1 );
+        }
+    }
+
+
+private:
+    //
+    // Initializes a thread object which has no associated executable function.
+    // This is used for the main thread initialized in thread_init().
+    //
+    this()
+    {
+        m_call = Call.NO;
+        m_curr = &m_main;
+
+        void* pstart = cast(void*) &_tlsstart;
+        void* pend   = cast(void*) &_tlsend;
+        m_tls = pstart[0 .. pend - pstart];
+    }
+
+
+    //
+    // Thread entry point.  Invokes the function or delegate passed on
+    // construction (if any).
+    //
+    final void run()
+    {
+        switch( m_call )
+        {
+        case Call.FN:
+            m_fn();
+            break;
+        case Call.DG:
+            m_dg();
+            break;
+        default:
+            break;
+        }
+    }
+
+
+private:
+    //
+    // The type of routine passed on thread construction.
+    //
+    enum Call
+    {
+        NO,
+        FN,
+        DG
+    }
+
+
+    //
+    // Standard types
+    //
+    version( Windows )
+    {
+        alias uint TLSKey;
+        alias uint ThreadAddr;
+    }
+    else version( Posix )
+    {
+        alias pthread_key_t TLSKey;
+        alias pthread_t     ThreadAddr;
+    }
+
+
+    //
+    // Local storage
+    //
+    __gshared bool[LOCAL_MAX]  sm_local;
+    __gshared TLSKey           sm_this;
+
+    void*[LOCAL_MAX]        m_local;
+
+
+    //
+    // Standard thread data
+    //
+    version( Windows )
+    {
+        HANDLE          m_hndl;
+    }
+    else version( OSX )
+    {
+        mach_port_t     m_tmach;
+    }
+    ThreadAddr          m_addr;
+    Call                m_call;
+    char[]              m_name;
+    union
+    {
+        void function() m_fn;
+        void delegate() m_dg;
+    }
+    size_t              m_sz;
+    version( Posix )
+    {
+        bool            m_isRunning;
+    }
+    bool                m_isDaemon;
+    Object              m_unhandled;
+
+
+private:
+    ///////////////////////////////////////////////////////////////////////////
+    // Storage of Active Thread
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    //
+    // Sets a thread-local reference to the current thread object.
+    //
+    static void setThis( Thread t )
+    {
+        version( Windows )
+        {
+            TlsSetValue( sm_this, cast(void*) t );
+        }
+        else version( Posix )
+        {
+            pthread_setspecific( sm_this, cast(void*) t );
+        }
+    }
+
+
+private:
+    ///////////////////////////////////////////////////////////////////////////
+    // Thread Context and GC Scanning Support
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    final void pushContext( Context* c )
+    in
+    {
+        assert( !c.within );
+    }
+    body
+    {
+        c.within = m_curr;
+        m_curr = c;
+    }
+
+
+    final void popContext()
+    in
+    {
+        assert( m_curr && m_curr.within );
+    }
+    body
+    {
+        Context* c = m_curr;
+        m_curr = c.within;
+        c.within = null;
+    }
+
+
+    final Context* topContext()
+    in
+    {
+        assert( m_curr );
+    }
+    body
+    {
+        return m_curr;
+    }
+
+
+    static struct Context
+    {
+        void*           bstack,
+                        tstack;
+        Context*        within;
+        Context*        next,
+                        prev;
+    }
+
+
+    Context             m_main;
+    Context*            m_curr;
+    bool                m_lock;
+    void[]              m_tls;  // spans implicit thread local storage
+
+    version( Windows )
+    {
+      version( X86 )
+      {
+        uint[8]         m_reg; // edi,esi,ebp,esp,ebx,edx,ecx,eax
+      }
+      else version( X86_64 )
+      {
+        ulong[16]       m_reg; // rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax
+                               // r8,r9,r10,r11,r12,r13,r14,r15
+      }
+      else
+      {
+        static assert( "Architecture not supported." );
+      }
+    }
+    else version( OSX )
+    {
+      version( X86 )
+      {
+        uint[8]         m_reg; // edi,esi,ebp,esp,ebx,edx,ecx,eax
+      }
+      else version( X86_64 )
+      {
+        ulong[16]       m_reg; // rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax
+                               // r8,r9,r10,r11,r12,r13,r14,r15
+      }
+      else
+      {
+        static assert( "Architecture not supported." );
+      }
+    }
+
+
+private:
+    ///////////////////////////////////////////////////////////////////////////
+    // GC Scanning Support
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    // NOTE: The GC scanning process works like so:
+    //
+    //          1. Suspend all threads.
+    //          2. Scan the stacks of all suspended threads for roots.
+    //          3. Resume all threads.
+    //
+    //       Step 1 and 3 require a list of all threads in the system, while
+    //       step 2 requires a list of all thread stacks (each represented by
+    //       a Context struct).  Traditionally, there was one stack per thread
+    //       and the Context structs were not necessary.  However, Fibers have
+    //       changed things so that each thread has its own 'main' stack plus
+    //       an arbitrary number of nested stacks (normally referenced via
+    //       m_curr).  Also, there may be 'free-floating' stacks in the system,
+    //       which are Fibers that are not currently executing on any specific
+    //       thread but are still being processed and still contain valid
+    //       roots.
+    //
+    //       To support all of this, the Context struct has been created to
+    //       represent a stack range, and a global list of Context structs has
+    //       been added to enable scanning of these stack ranges.  The lifetime
+    //       (and presence in the Context list) of a thread's 'main' stack will
+    //       be equivalent to the thread's lifetime.  So the Ccontext will be
+    //       added to the list on thread entry, and removed from the list on
+    //       thread exit (which is essentially the same as the presence of a
+    //       Thread object in its own global list).  The lifetime of a Fiber's
+    //       context, however, will be tied to the lifetime of the Fiber object
+    //       itself, and Fibers are expected to add/remove their Context struct
+    //       on construction/deletion.
+
+
+    //
+    // All use of the global lists should synchronize on this lock.
+    //
+    static Object slock()
+    {
+        return Thread.classinfo;
+    }
+
+
+    __gshared
+    {
+	Context*     sm_cbeg;
+	size_t       sm_clen;
+
+	Thread       sm_tbeg;
+	size_t       sm_tlen;
+    }
+
+    //
+    // Used for ordering threads in the global thread list.
+    //
+    Thread              prev;
+    Thread              next;
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Global Context List Operations
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    //
+    // Add a context to the global context list.
+    //
+    static void add( Context* c )
+    in
+    {
+        assert( c );
+        assert( !c.next && !c.prev );
+    }
+    body
+    {
+        synchronized( slock )
+        {
+            if( sm_cbeg )
+            {
+                c.next = sm_cbeg;
+                sm_cbeg.prev = c;
+            }
+            sm_cbeg = c;
+            ++sm_clen;
+        }
+    }
+
+
+    //
+    // Remove a context from the global context list.
+    //
+    static void remove( Context* c )
+    in
+    {
+        assert( c );
+        assert( c.next || c.prev );
+    }
+    body
+    {
+        synchronized( slock )
+        {
+            if( c.prev )
+                c.prev.next = c.next;
+            if( c.next )
+                c.next.prev = c.prev;
+            if( sm_cbeg == c )
+                sm_cbeg = c.next;
+            --sm_clen;
+        }
+        // NOTE: Don't null out c.next or c.prev because opApply currently
+        //       follows c.next after removing a node.  This could be easily
+        //       addressed by simply returning the next node from this
+        //       function, however, a context should never be re-added to the
+        //       list anyway and having next and prev be non-null is a good way
+        //       to ensure that.
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Global Thread List Operations
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    //
+    // Add a thread to the global thread list.
+    //
+    static void add( Thread t )
+    in
+    {
+        assert( t );
+        assert( !t.next && !t.prev );
+        assert( t.isRunning );
+    }
+    body
+    {
+        synchronized( slock )
+        {
+            if( sm_tbeg )
+            {
+                t.next = sm_tbeg;
+                sm_tbeg.prev = t;
+            }
+            sm_tbeg = t;
+            ++sm_tlen;
+        }
+    }
+
+
+    //
+    // Remove a thread from the global thread list.
+    //
+    static void remove( Thread t )
+    in
+    {
+        assert( t );
+        assert( t.next || t.prev );
+        version( Windows )
+        {
+            // NOTE: This doesn't work for Posix as m_isRunning must be set to
+            //       false after the thread is removed during normal execution.
+            assert( !t.isRunning );
+        }
+    }
+    body
+    {
+        synchronized( slock )
+        {
+            // NOTE: When a thread is removed from the global thread list its
+            //       main context is invalid and should be removed as well.
+            //       It is possible that t.m_curr could reference more
+            //       than just the main context if the thread exited abnormally
+            //       (if it was terminated), but we must assume that the user
+            //       retains a reference to them and that they may be re-used
+            //       elsewhere.  Therefore, it is the responsibility of any
+            //       object that creates contexts to clean them up properly
+            //       when it is done with them.
+            remove( &t.m_main );
+
+            if( t.prev )
+                t.prev.next = t.next;
+            if( t.next )
+                t.next.prev = t.prev;
+            if( sm_tbeg == t )
+                sm_tbeg = t.next;
+            --sm_tlen;
+        }
+        // NOTE: Don't null out t.next or t.prev because opApply currently
+        //       follows t.next after removing a node.  This could be easily
+        //       addressed by simply returning the next node from this
+        //       function, however, a thread should never be re-added to the
+        //       list anyway and having next and prev be non-null is a good way
+        //       to ensure that.
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// GC Support Routines
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Initializes the thread module.  This function must be called by the
+ * garbage collector on startup and before any other thread routines
+ * are called.
+ */
+extern (C) void thread_init()
+{
+    // NOTE: If thread_init itself performs any allocations then the thread
+    //       routines reserved for garbage collector use may be called while
+    //       thread_init is being processed.  However, since no memory should
+    //       exist to be scanned at this point, it is sufficient for these
+    //       functions to detect the condition and return immediately.
+
+    version( Windows )
+    {
+        Thread.sm_this = TlsAlloc();
+        assert( Thread.sm_this != TLS_OUT_OF_INDEXES );
+    }
+    else version( Posix )
+    {
+        int         status;
+        sigaction_t sigusr1 = void;
+        sigaction_t sigusr2 = void;
+
+        // This is a quick way to zero-initialize the structs without using
+        // memset or creating a link dependency on their static initializer.
+        (cast(byte*) &sigusr1)[0 .. sigaction_t.sizeof] = 0;
+        (cast(byte*) &sigusr2)[0 .. sigaction_t.sizeof] = 0;
+
+        // NOTE: SA_RESTART indicates that system calls should restart if they
+        //       are interrupted by a signal, but this is not available on all
+        //       Posix systems, even those that support multithreading.
+        static if( is( typeof( SA_RESTART ) ) )
+            sigusr1.sa_flags = SA_RESTART;
+        else
+            sigusr1.sa_flags   = 0;
+        sigusr1.sa_handler = &thread_suspendHandler;
+        // NOTE: We want to ignore all signals while in this handler, so fill
+        //       sa_mask to indicate this.
+        status = sigfillset( &sigusr1.sa_mask );
+        assert( status == 0 );
+
+        // NOTE: Since SIGUSR2 should only be issued for threads within the
+        //       suspend handler, we don't want this signal to trigger a
+        //       restart.
+        sigusr2.sa_flags   = 0;
+        sigusr2.sa_handler = &thread_resumeHandler;
+        // NOTE: We want to ignore all signals while in this handler, so fill
+        //       sa_mask to indicate this.
+        status = sigfillset( &sigusr2.sa_mask );
+        assert( status == 0 );
+
+        status = sigaction( SIGUSR1, &sigusr1, null );
+        assert( status == 0 );
+
+        status = sigaction( SIGUSR2, &sigusr2, null );
+        assert( status == 0 );
+
+        status = sem_init( &suspendCount, 0, 0 );
+        assert( status == 0 );
+
+        status = pthread_key_create( &Thread.sm_this, null );
+        assert( status == 0 );
+    }
+
+    thread_attachThis();
+}
+
+
+/**
+ * Registers the calling thread for use with the D Runtime.  If this routine
+ * is called for a thread which is already registered, the result is undefined.
+ */
+extern (C) void thread_attachThis()
+{
+    version( Windows )
+    {
+        Thread          thisThread  = new Thread();
+        Thread.Context* thisContext = &thisThread.m_main;
+        assert( thisContext == thisThread.m_curr );
+
+        thisThread.m_addr  = GetCurrentThreadId();
+        thisThread.m_hndl  = GetCurrentThreadHandle();
+        thisContext.bstack = getStackBottom();
+        thisContext.tstack = thisContext.bstack;
+
+        thisThread.m_isDaemon = true;
+
+        Thread.setThis( thisThread );
+    }
+    else version( Posix )
+    {
+        Thread          thisThread  = new Thread();
+        Thread.Context* thisContext = thisThread.m_curr;
+        assert( thisContext == &thisThread.m_main );
+
+        thisThread.m_addr  = pthread_self();
+        thisContext.bstack = getStackBottom();
+        thisContext.tstack = thisContext.bstack;
+
+        thisThread.m_isRunning = true;
+        thisThread.m_isDaemon  = true;
+
+        Thread.setThis( thisThread );
+    }
+    version( OSX )
+    {
+        thisThread.m_tmach = pthread_mach_thread_np( thisThread.m_addr );
+        assert( thisThread.m_tmach != thisThread.m_tmach.init );
+    }    
+
+    Thread.add( thisThread );
+    Thread.add( thisContext );
+}
+
+
+/**
+ * Deregisters the calling thread from use with the runtime.  If this routine
+ * is called for a thread which is already registered, the result is undefined.
+ */
+extern (C) void thread_detachThis()
+{
+    Thread.remove( Thread.getThis() );
+}
+
+
+/**
+ * Joins all non-daemon threads that are currently running.  This is done by
+ * performing successive scans through the thread list until a scan consists
+ * of only daemon threads.
+ */
+extern (C) void thread_joinAll()
+{
+
+    while( true )
+    {
+        Thread nonDaemon = null;
+
+        foreach( t; Thread )
+        {
+            if( !t.isDaemon )
+            {
+                nonDaemon = t;
+                break;
+            }
+        }
+        if( nonDaemon is null )
+            return;
+        nonDaemon.join();
+    }
+}
+
+
+/**
+ * Performs intermediate shutdown of the thread module.
+ */
+static ~this()
+{
+    // NOTE: The functionality related to garbage collection must be minimally
+    //       operable after this dtor completes.  Therefore, only minimal
+    //       cleanup may occur.
+
+    for( Thread t = Thread.sm_tbeg; t; t = t.next )
+    {
+        if( !t.isRunning )
+            Thread.remove( t );
+    }
+}
+
+
+// Used for needLock below
+private __gshared bool multiThreadedFlag = false;
+
+
+/**
+ * This function is used to determine whether the the process is
+ * multi-threaded.  Optimizations may only be performed on this
+ * value if the programmer can guarantee that no path from the
+ * enclosed code will start a thread.
+ *
+ * Returns:
+ *  True if Thread.start() has been called in this process.
+ */
+extern (C) bool thread_needLock()
+{
+    return multiThreadedFlag;
+}
+
+
+// Used for suspendAll/resumeAll below
+private __gshared uint suspendDepth = 0;
+
+
+/**
+ * Suspend all threads but the calling thread for "stop the world" garbage
+ * collection runs.  This function may be called multiple times, and must
+ * be followed by a matching number of calls to thread_resumeAll before
+ * processing is resumed.
+ *
+ * Throws:
+ *  ThreadException if the suspend operation fails for a running thread.
+ */
+extern (C) void thread_suspendAll()
+{
+    /**
+     * Suspend the specified thread and load stack and register information for
+     * use by thread_scanAll.  If the supplied thread is the calling thread,
+     * stack and register information will be loaded but the thread will not
+     * be suspended.  If the suspend operation fails and the thread is not
+     * running then it will be removed from the global thread list, otherwise
+     * an exception will be thrown.
+     *
+     * Params:
+     *  t = The thread to suspend.
+     *
+     * Throws:
+     *  ThreadException if the suspend operation fails for a running thread.
+     */
+    void suspend( Thread t )
+    {
+        version( Windows )
+        {
+            if( t.m_addr != GetCurrentThreadId() && SuspendThread( t.m_hndl ) == 0xFFFFFFFF )
+            {
+                if( !t.isRunning )
+                {
+                    Thread.remove( t );
+                    return;
+                }
+                throw new ThreadException( "Unable to suspend thread" );
+            }
+
+            CONTEXT context = void;
+            context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
+
+            if( !GetThreadContext( t.m_hndl, &context ) )
+                throw new ThreadException( "Unable to load thread context" );
+
+            version( X86 )
+            {
+                if( !t.m_lock )
+                    t.m_curr.tstack = cast(void*) context.Esp;
+                // eax,ebx,ecx,edx,edi,esi,ebp,esp
+                t.m_reg[0] = context.Eax;
+                t.m_reg[1] = context.Ebx;
+                t.m_reg[2] = context.Ecx;
+                t.m_reg[3] = context.Edx;
+                t.m_reg[4] = context.Edi;
+                t.m_reg[5] = context.Esi;
+                t.m_reg[6] = context.Ebp;
+                t.m_reg[7] = context.Esp;
+            }
+            else
+            {
+                static assert( "Architecture not supported." );
+            }
+        }
+        else version( OSX )
+        {
+            if( t.m_addr != pthread_self() && thread_suspend( t.m_tmach ) != KERN_SUCCESS )
+            {
+                if( !t.isRunning )
+                {
+                    Thread.remove( t );
+                    return;
+                }
+                throw new ThreadException( "Unable to suspend thread" );
+            }
+
+            version( X86 )
+            {
+                x86_thread_state32_t    state = void;
+                mach_msg_type_number_t  count = x86_THREAD_STATE32_COUNT;
+
+                if( thread_get_state( t.m_tmach, x86_THREAD_STATE32, &state, &count ) != KERN_SUCCESS )
+                    throw new ThreadException( "Unable to load thread state" );
+                if( !t.m_lock )
+                    t.m_curr.tstack = cast(void*) state.esp;
+                // eax,ebx,ecx,edx,edi,esi,ebp,esp
+                t.m_reg[0] = state.eax;
+                t.m_reg[1] = state.ebx;
+                t.m_reg[2] = state.ecx;
+                t.m_reg[3] = state.edx;
+                t.m_reg[4] = state.edi;
+                t.m_reg[5] = state.esi;
+                t.m_reg[6] = state.ebp;
+                t.m_reg[7] = state.esp;
+            }
+            else version( X86_64 )
+            {
+                x86_thread_state64_t    state = void;
+                mach_msg_type_number_t  count = x86_THREAD_STATE64_COUNT;
+
+                if( thread_get_state( t.m_tmach, x86_THREAD_STATE64, &state, &count ) != KERN_SUCCESS )
+                    throw new ThreadException( "Unable to load thread state" );
+                if( !t.m_lock )
+                    t.m_curr.tstack = cast(void*) state.rsp;
+                // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp
+                t.m_reg[0] = state.rax;
+                t.m_reg[1] = state.rbx;
+                t.m_reg[2] = state.rcx;
+                t.m_reg[3] = state.rdx;
+                t.m_reg[4] = state.rdi;
+                t.m_reg[5] = state.rsi;
+                t.m_reg[6] = state.rbp;
+                t.m_reg[7] = state.rsp;
+                // r8,r9,r10,r11,r12,r13,r14,r15
+                t.m_reg[8]  = state.r8;
+                t.m_reg[9]  = state.r9;
+                t.m_reg[10] = state.r10;
+                t.m_reg[11] = state.r11;
+                t.m_reg[12] = state.r12;
+                t.m_reg[13] = state.r13;
+                t.m_reg[14] = state.r14;
+                t.m_reg[15] = state.r15;
+            }
+            else
+            {
+                static assert( "Architecture not supported." );
+            }
+        }
+        else version( Posix )
+        {
+            if( t.m_addr != pthread_self() )
+            {
+                if( pthread_kill( t.m_addr, SIGUSR1 ) != 0 )
+                {
+                    if( !t.isRunning )
+                    {
+                        Thread.remove( t );
+                        return;
+                    }
+                    throw new ThreadException( "Unable to suspend thread" );
+                }
+                // NOTE: It's really not ideal to wait for each thread to
+                //       signal individually -- rather, it would be better to
+                //       suspend them all and wait once at the end.  However,
+                //       semaphores don't really work this way, and the obvious
+                //       alternative (looping on an atomic suspend count)
+                //       requires either the atomic module (which only works on
+                //       x86) or other specialized functionality.  It would
+                //       also be possible to simply loop on sem_wait at the
+                //       end, but I'm not convinced that this would be much
+                //       faster than the current approach.
+                sem_wait( &suspendCount );
+            }
+            else if( !t.m_lock )
+            {
+                t.m_curr.tstack = getStackTop();
+            }
+        }
+    }
+
+
+    // NOTE: We've got an odd chicken & egg problem here, because while the GC
+    //       is required to call thread_init before calling any other thread
+    //       routines, thread_init may allocate memory which could in turn
+    //       trigger a collection.  Thus, thread_suspendAll, thread_scanAll,
+    //       and thread_resumeAll must be callable before thread_init
+    //       completes, with the assumption that no other GC memory has yet
+    //       been allocated by the system, and thus there is no risk of losing
+    //       data if the global thread list is empty.  The check of
+    //       Thread.sm_tbeg below is done to ensure thread_init has completed,
+    //       and therefore that calling Thread.getThis will not result in an
+    //       error.  For the short time when Thread.sm_tbeg is null, there is
+    //       no reason not to simply call the multithreaded code below, with
+    //       the expectation that the foreach loop will never be entered.
+    if( !multiThreadedFlag && Thread.sm_tbeg )
+    {
+        if( ++suspendDepth == 1 )
+            suspend( Thread.getThis() );
+        return;
+    }
+    synchronized( Thread.slock )
+    {
+        if( ++suspendDepth > 1 )
+            return;
+
+        // NOTE: I'd really prefer not to check isRunning within this loop but
+        //       not doing so could be problematic if threads are termianted
+        //       abnormally and a new thread is created with the same thread
+        //       address before the next GC run.  This situation might cause
+        //       the same thread to be suspended twice, which would likely
+        //       cause the second suspend to fail, the garbage collection to
+        //       abort, and Bad Things to occur.
+        for( Thread t = Thread.sm_tbeg; t; t = t.next )
+        {
+            if( t.isRunning )
+                suspend( t );
+            else
+                Thread.remove( t );
+        }
+
+        version( Posix )
+        {
+            // wait on semaphore -- see note in suspend for
+            // why this is currently not implemented
+        }
+    }
+}
+
+
+/**
+ * Resume all threads but the calling thread for "stop the world" garbage
+ * collection runs.  This function must be called once for each preceding
+ * call to thread_suspendAll before the threads are actually resumed.
+ *
+ * In:
+ *  This routine must be preceded by a call to thread_suspendAll.
+ *
+ * Throws:
+ *  ThreadException if the resume operation fails for a running thread.
+ */
+extern (C) void thread_resumeAll()
+in
+{
+    assert( suspendDepth > 0 );
+}
+body
+{
+    /**
+     * Resume the specified thread and unload stack and register information.
+     * If the supplied thread is the calling thread, stack and register
+     * information will be unloaded but the thread will not be resumed.  If
+     * the resume operation fails and the thread is not running then it will
+     * be removed from the global thread list, otherwise an exception will be
+     * thrown.
+     *
+     * Params:
+     *  t = The thread to resume.
+     *
+     * Throws:
+     *  ThreadException if the resume fails for a running thread.
+     */
+    void resume( Thread t )
+    {
+        version( Windows )
+        {
+            if( t.m_addr != GetCurrentThreadId() && ResumeThread( t.m_hndl ) == 0xFFFFFFFF )
+            {
+                if( !t.isRunning )
+                {
+                    Thread.remove( t );
+                    return;
+                }
+                throw new ThreadException( "Unable to resume thread" );
+            }
+
+            if( !t.m_lock )
+                t.m_curr.tstack = t.m_curr.bstack;
+            t.m_reg[0 .. $] = 0;
+        }
+        else version( OSX )
+        {
+            if( t.m_addr != pthread_self() && thread_resume( t.m_tmach ) != KERN_SUCCESS )
+            {
+                if( !t.isRunning )
+                {
+                    Thread.remove( t );
+                    return;
+                }
+                throw new ThreadException( "Unable to resume thread" );
+            }
+
+            if( !t.m_lock )
+                t.m_curr.tstack = t.m_curr.bstack;
+            t.m_reg[0 .. $] = 0;
+        }
+        else version( Posix )
+        {
+            if( t.m_addr != pthread_self() )
+            {
+                if( pthread_kill( t.m_addr, SIGUSR2 ) != 0 )
+                {
+                    if( !t.isRunning )
+                    {
+                        Thread.remove( t );
+                        return;
+                    }
+                    throw new ThreadException( "Unable to resume thread" );
+                }
+            }
+            else if( !t.m_lock )
+            {
+                t.m_curr.tstack = t.m_curr.bstack;
+            }
+        }
+    }
+
+
+    // NOTE: See thread_suspendAll for the logic behind this.
+    if( !multiThreadedFlag && Thread.sm_tbeg )
+    {
+        if( --suspendDepth == 0 )
+            resume( Thread.getThis() );
+        return;
+    }
+    synchronized( Thread.slock )
+    {
+        if( --suspendDepth > 0 )
+            return;
+
+        for( Thread t = Thread.sm_tbeg; t; t = t.next )
+        {
+            resume( t );
+        }
+    }
+}
+
+
+private alias void delegate( void*, void* ) scanAllThreadsFn;
+
+
+/**
+ * The main entry point for garbage collection.  The supplied delegate
+ * will be passed ranges representing both stack and register values.
+ *
+ * Params:
+ *  scan        = The scanner function.  It should scan from p1 through p2 - 1.
+ *  curStackTop = An optional pointer to the top of the calling thread's stack.
+ *
+ * In:
+ *  This routine must be preceded by a call to thread_suspendAll.
+ */
+extern (C) void thread_scanAll( scanAllThreadsFn scan, void* curStackTop = null )
+in
+{
+    assert( suspendDepth > 0 );
+}
+body
+{
+    Thread  thisThread  = null;
+    void*   oldStackTop = null;
+
+    if( curStackTop && Thread.sm_tbeg )
+    {
+        thisThread  = Thread.getThis();
+        if( !thisThread.m_lock )
+        {
+            oldStackTop = thisThread.m_curr.tstack;
+            thisThread.m_curr.tstack = curStackTop;
+        }
+    }
+
+    scope( exit )
+    {
+        if( curStackTop && Thread.sm_tbeg )
+        {
+            if( !thisThread.m_lock )
+            {
+                thisThread.m_curr.tstack = oldStackTop;
+            }
+        }
+    }
+
+    // NOTE: Synchronizing on Thread.slock is not needed because this
+    //       function may only be called after all other threads have
+    //       been suspended from within the same lock.
+    for( Thread.Context* c = Thread.sm_cbeg; c; c = c.next )
+    {
+        version( StackGrowsDown )
+        {
+            // NOTE: We can't index past the bottom of the stack
+            //       so don't do the "+1" for StackGrowsDown.
+            if( c.tstack && c.tstack < c.bstack )
+                scan( c.tstack, c.bstack );
+        }
+        else
+        {
+            if( c.bstack && c.bstack < c.tstack )
+                scan( c.bstack, c.tstack + 1 );
+        }
+    }
+
+    for( Thread t = Thread.sm_tbeg; t; t = t.next )
+    {
+        scan( &t.m_tls[0], &t.m_tls[0] + t.m_tls.length );
+
+        version( Windows )
+        {
+            scan( &t.m_reg[0], &t.m_reg[0] + t.m_reg.length );
+        }
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Thread Local
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This class encapsulates the operations required to initialize, access, and
+ * destroy thread local data.
+ */
+class ThreadLocal( T )
+{
+    ///////////////////////////////////////////////////////////////////////////
+    // Initialization
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Initializes thread local storage for the indicated value which will be
+     * initialized to def for all threads.
+     *
+     * Params:
+     *  def = The default value to return if no value has been explicitly set.
+     */
+    this( T def = T.init )
+    {
+        m_def = def;
+        m_key = Thread.createLocal();
+    }
+
+
+    ~this()
+    {
+        Thread.deleteLocal( m_key );
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Accessors
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Gets the value last set by the calling thread, or def if no such value
+     * has been set.
+     *
+     * Returns:
+     *  The stored value or def if no value is stored.
+     */
+    T val()
+    {
+        Wrap* wrap = cast(Wrap*) Thread.getLocal( m_key );
+
+        return wrap ? wrap.val : m_def;
+    }
+
+
+    /**
+     * Copies newval to a location specific to the calling thread, and returns
+     * newval.
+     *
+     * Params:
+     *  newval = The value to set.
+     *
+     * Returns:
+     *  The value passed to this function.
+     */
+    T val( T newval )
+    {
+        Wrap* wrap = cast(Wrap*) Thread.getLocal( m_key );
+
+        if( wrap is null )
+        {
+            wrap = new Wrap;
+            Thread.setLocal( m_key, wrap );
+        }
+        wrap.val = newval;
+        return newval;
+    }
+
+
+private:
+    //
+    // A wrapper for the stored data.  This is needed for determining whether
+    // set has ever been called for this thread (and therefore whether the
+    // default value should be returned) and also to flatten the differences
+    // between data that is smaller and larger than (void*).sizeof.  The
+    // obvious tradeoff here is an extra per-thread allocation for each
+    // ThreadLocal value as compared to calling the Thread routines directly.
+    //
+    struct Wrap
+    {
+        T   val;
+    }
+
+
+    T       m_def;
+    uint    m_key;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Thread Group
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This class is intended to simplify certain common programming techniques.
+ */
+class ThreadGroup
+{
+    /**
+     * Creates and starts a new Thread object that executes fn and adds it to
+     * the list of tracked threads.
+     *
+     * Params:
+     *  fn = The thread function.
+     *
+     * Returns:
+     *  A reference to the newly created thread.
+     */
+    final Thread create( void function() fn )
+    {
+        Thread t = new Thread( fn );
+
+        t.start();
+        synchronized( this )
+        {
+            m_all[t] = t;
+        }
+        return t;
+    }
+
+
+    /**
+     * Creates and starts a new Thread object that executes dg and adds it to
+     * the list of tracked threads.
+     *
+     * Params:
+     *  dg = The thread function.
+     *
+     * Returns:
+     *  A reference to the newly created thread.
+     */
+    final Thread create( void delegate() dg )
+    {
+        Thread t = new Thread( dg );
+
+        t.start();
+        synchronized( this )
+        {
+            m_all[t] = t;
+        }
+        return t;
+    }
+
+
+    /**
+     * Add t to the list of tracked threads if it is not already being tracked.
+     *
+     * Params:
+     *  t = The thread to add.
+     *
+     * In:
+     *  t must not be null.
+     */
+    final void add( Thread t )
+    in
+    {
+        assert( t );
+    }
+    body
+    {
+        synchronized( this )
+        {
+            m_all[t] = t;
+        }
+    }
+
+
+    /**
+     * Removes t from the list of tracked threads.  No operation will be
+     * performed if t is not currently being tracked by this object.
+     *
+     * Params:
+     *  t = The thread to remove.
+     *
+     * In:
+     *  t must not be null.
+     */
+    final void remove( Thread t )
+    in
+    {
+        assert( t );
+    }
+    body
+    {
+        synchronized( this )
+        {
+            m_all.remove( t );
+        }
+    }
+
+
+    /**
+     * Operates on all threads currently tracked by this object.
+     */
+    final int opApply( int delegate( inout Thread ) dg )
+    {
+        synchronized( this )
+        {
+            int ret = 0;
+
+            // NOTE: This loop relies on the knowledge that m_all uses the
+            //       Thread object for both the key and the mapped value.
+            foreach( Thread t; m_all.keys )
+            {
+                ret = dg( t );
+                if( ret )
+                    break;
+            }
+            return ret;
+        }
+    }
+
+
+    /**
+     * Iteratively joins all tracked threads.  This function will block add,
+     * remove, and opApply until it completes.
+     *
+     * Params:
+     *  rethrow = Rethrow any unhandled exception which may have caused the
+     *            current thread to terminate.
+     *
+     * Throws:
+     *  Any exception not handled by the joined threads.
+     */
+    final void joinAll( bool rethrow = true )
+    {
+        synchronized( this )
+        {
+            // NOTE: This loop relies on the knowledge that m_all uses the
+            //       Thread object for both the key and the mapped value.
+            foreach( Thread t; m_all.keys )
+            {
+                t.join( rethrow );
+            }
+        }
+    }
+
+
+private:
+    Thread[Thread]  m_all;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Fiber Platform Detection and Memory Allocation
+///////////////////////////////////////////////////////////////////////////////
+
+
+private
+{
+    version( D_InlineAsm_X86 )
+    {
+        version( X86_64 )
+        {
+
+        }
+        else
+        {
+            version( Windows )
+                version = AsmX86_Win32;
+            else version( Posix )
+                version = AsmX86_Posix;
+        }
+    }
+    else version( PPC )
+    {
+        version( Posix )
+            version = AsmPPC_Posix;
+    }
+
+
+    version( Posix )
+    {
+        import core.sys.posix.unistd;   // for sysconf
+        import core.sys.posix.sys.mman; // for mmap
+        import core.sys.posix.stdlib;   // for malloc, valloc, free
+
+        version( AsmX86_Win32 ) {} else
+        version( AsmX86_Posix ) {} else
+        version( AsmPPC_Posix ) {} else
+        {
+            // NOTE: The ucontext implementation requires architecture specific
+            //       data definitions to operate so testing for it must be done
+            //       by checking for the existence of ucontext_t rather than by
+            //       a version identifier.  Please note that this is considered
+            //       an obsolescent feature according to the POSIX spec, so a
+            //       custom solution is still preferred.
+            import core.sys.posix.ucontext;
+        }
+    }
+
+    const size_t PAGESIZE;
+}
+
+
+static this()
+{
+    static if( is( typeof( GetSystemInfo ) ) )
+    {
+        SYSTEM_INFO info;
+        GetSystemInfo( &info );
+
+        PAGESIZE = info.dwPageSize;
+        assert( PAGESIZE < int.max );
+    }
+    else static if( is( typeof( sysconf ) ) &&
+                    is( typeof( _SC_PAGESIZE ) ) )
+    {
+        PAGESIZE = cast(size_t) sysconf( _SC_PAGESIZE );
+        assert( PAGESIZE < int.max );
+    }
+    else
+    {
+        version( PPC )
+            PAGESIZE = 8192;
+        else
+            PAGESIZE = 4096;
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Fiber Entry Point and Context Switch
+///////////////////////////////////////////////////////////////////////////////
+
+
+private
+{
+    extern (C) void fiber_entryPoint()
+    {
+        Fiber   obj = Fiber.getThis();
+        assert( obj );
+
+        assert( Thread.getThis().m_curr is obj.m_ctxt );
+        volatile Thread.getThis().m_lock = false;
+        obj.m_ctxt.tstack = obj.m_ctxt.bstack;
+        obj.m_state = Fiber.State.EXEC;
+
+        try
+        {
+            obj.run();
+        }
+        catch( Object o )
+        {
+            obj.m_unhandled = o;
+        }
+
+        static if( is( ucontext_t ) )
+          obj.m_ucur = &obj.m_utxt;
+
+        obj.m_state = Fiber.State.TERM;
+        obj.switchOut();
+    }
+
+
+  // NOTE: If AsmPPC_Posix is defined then the context switch routine will
+  //       be defined externally until GDC supports inline PPC ASM.
+  version( AsmPPC_Posix )
+    extern (C) void fiber_switchContext( void** oldp, void* newp );
+  else
+    extern (C) void fiber_switchContext( void** oldp, void* newp )
+    {
+        // NOTE: The data pushed and popped in this routine must match the
+        //       default stack created by Fiber.initStack or the initial
+        //       switch into a new context will fail.
+
+        version( AsmX86_Win32 )
+        {
+            asm
+            {
+                naked;
+
+                // save current stack state
+                push EBP;
+                mov  EBP, ESP;
+                push EAX;
+                push dword ptr FS:[0];
+                push dword ptr FS:[4];
+                push dword ptr FS:[8];
+                push EBX;
+                push ESI;
+                push EDI;
+
+                // store oldp again with more accurate address
+                mov EAX, dword ptr 8[EBP];
+                mov [EAX], ESP;
+                // load newp to begin context switch
+                mov ESP, dword ptr 12[EBP];
+
+                // load saved state from new stack
+                pop EDI;
+                pop ESI;
+                pop EBX;
+                pop dword ptr FS:[8];
+                pop dword ptr FS:[4];
+                pop dword ptr FS:[0];
+                pop EAX;
+                pop EBP;
+
+                // 'return' to complete switch
+                ret;
+            }
+        }
+        else version( AsmX86_Posix )
+        {
+            asm
+            {
+                naked;
+
+                // save current stack state
+                push EBP;
+                mov  EBP, ESP;
+                push EAX;
+                push EBX;
+                push ESI;
+                push EDI;
+
+                // store oldp again with more accurate address
+                mov EAX, dword ptr 8[EBP];
+                mov [EAX], ESP;
+                // load newp to begin context switch
+                mov ESP, dword ptr 12[EBP];
+
+                // load saved state from new stack
+                pop EDI;
+                pop ESI;
+                pop EBX;
+                pop EAX;
+                pop EBP;
+
+                // 'return' to complete switch
+                ret;
+            }
+        }
+        else static if( is( ucontext_t ) )
+        {
+            Fiber   cfib = Fiber.getThis();
+            void*   ucur = cfib.m_ucur;
+
+            *oldp = &ucur;
+            swapcontext( **(cast(ucontext_t***) oldp),
+                          *(cast(ucontext_t**)  newp) );
+        }
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Fiber
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This class provides a cooperative concurrency mechanism integrated with the
+ * threading and garbage collection functionality.  Calling a fiber may be
+ * considered a blocking operation that returns when the fiber yields (via
+ * Fiber.yield()).  Execution occurs within the context of the calling thread
+ * so synchronization is not necessary to guarantee memory visibility so long
+ * as the same thread calls the fiber each time.  Please note that there is no
+ * requirement that a fiber be bound to one specific thread.  Rather, fibers
+ * may be freely passed between threads so long as they are not currently
+ * executing.  Like threads, a new fiber thread may be created using either
+ * derivation or composition, as in the following example.
+ *
+ * Example:
+ * ----------------------------------------------------------------------
+ *
+ * class DerivedFiber : Fiber
+ * {
+ *     this()
+ *     {
+ *         super( &run );
+ *     }
+ *
+ * private :
+ *     void run()
+ *     {
+ *         printf( "Derived fiber running.\n" );
+ *     }
+ * }
+ *
+ * void fiberFunc()
+ * {
+ *     printf( "Composed fiber running.\n" );
+ *     Fiber.yield();
+ *     printf( "Composed fiber running.\n" );
+ * }
+ *
+ * // create instances of each type
+ * Fiber derived = new DerivedFiber();
+ * Fiber composed = new Fiber( &fiberFunc );
+ *
+ * // call both fibers once
+ * derived.call();
+ * composed.call();
+ * printf( "Execution returned to calling context.\n" );
+ * composed.call();
+ *
+ * // since each fiber has run to completion, each should have state TERM
+ * assert( derived.state == Fiber.State.TERM );
+ * assert( composed.state == Fiber.State.TERM );
+ *
+ * ----------------------------------------------------------------------
+ *
+ * Authors: Based on a design by Mikola Lysenko.
+ */
+class Fiber
+{
+    ///////////////////////////////////////////////////////////////////////////
+    // Initialization
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Initializes a fiber object which is associated with a static
+     * D function.
+     *
+     * Params:
+     *  fn = The thread function.
+     *  sz = The stack size for this fiber.
+     *
+     * In:
+     *  fn must not be null.
+     */
+    this( void function() fn, size_t sz = PAGESIZE )
+    in
+    {
+        assert( fn );
+    }
+    body
+    {
+        m_fn    = fn;
+        m_call  = Call.FN;
+        m_state = State.HOLD;
+        allocStack( sz );
+        initStack();
+    }
+
+
+    /**
+     * Initializes a fiber object which is associated with a dynamic
+     * D function.
+     *
+     * Params:
+     *  dg = The thread function.
+     *  sz = The stack size for this fiber.
+     *
+     * In:
+     *  dg must not be null.
+     */
+    this( void delegate() dg, size_t sz = PAGESIZE )
+    in
+    {
+        assert( dg );
+    }
+    body
+    {
+        m_dg    = dg;
+        m_call  = Call.DG;
+        m_state = State.HOLD;
+        allocStack( sz );
+        initStack();
+    }
+
+
+    /**
+     * Cleans up any remaining resources used by this object.
+     */
+    ~this()
+    {
+        // NOTE: A live reference to this object will exist on its associated
+        //       stack from the first time its call() method has been called
+        //       until its execution completes with State.TERM.  Thus, the only
+        //       times this dtor should be called are either if the fiber has
+        //       terminated (and therefore has no active stack) or if the user
+        //       explicitly deletes this object.  The latter case is an error
+        //       but is not easily tested for, since State.HOLD may imply that
+        //       the fiber was just created but has never been run.  There is
+        //       not a compelling case to create a State.INIT just to offer a
+        //       means of ensuring the user isn't violating this object's
+        //       contract, so for now this requirement will be enforced by
+        //       documentation only.
+        freeStack();
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // General Actions
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Transfers execution to this fiber object.  The calling context will be
+     * suspended until the fiber calls Fiber.yield() or until it terminates
+     * via an unhandled exception.
+     *
+     * Params:
+     *  rethrow = Rethrow any unhandled exception which may have caused this
+     *            fiber to terminate.
+     *
+     * In:
+     *  This fiber must be in state HOLD.
+     *
+     * Throws:
+     *  Any exception not handled by the joined thread.
+     *
+     * Returns:
+     *  Any exception not handled by this fiber if rethrow = false, null
+     *  otherwise.
+     */
+    final Object call( bool rethrow = true )
+    in
+    {
+        assert( m_state == State.HOLD );
+    }
+    body
+    {
+        Fiber   cur = getThis();
+
+        static if( is( ucontext_t ) )
+          m_ucur = cur ? &cur.m_utxt : &Fiber.sm_utxt;
+
+        setThis( this );
+        this.switchIn();
+        setThis( cur );
+
+        static if( is( ucontext_t ) )
+          m_ucur = null;
+
+        // NOTE: If the fiber has terminated then the stack pointers must be
+        //       reset.  This ensures that the stack for this fiber is not
+        //       scanned if the fiber has terminated.  This is necessary to
+        //       prevent any references lingering on the stack from delaying
+        //       the collection of otherwise dead objects.  The most notable
+        //       being the current object, which is referenced at the top of
+        //       fiber_entryPoint.
+        if( m_state == State.TERM )
+        {
+            m_ctxt.tstack = m_ctxt.bstack;
+        }
+        if( m_unhandled )
+        {
+            Object obj  = m_unhandled;
+            m_unhandled = null;
+            if( rethrow )
+                throw obj;
+            return obj;
+        }
+        return null;
+    }
+
+
+    /**
+     * Resets this fiber so that it may be re-used.  This routine may only be
+     * called for fibers that have terminated, as doing otherwise could result
+     * in scope-dependent functionality that is not executed.  Stack-based
+     * classes, for example, may not be cleaned up properly if a fiber is reset
+     * before it has terminated.
+     *
+     * In:
+     *  This fiber must be in state TERM.
+     */
+    final void reset()
+    in
+    {
+        assert( m_state == State.TERM );
+        assert( m_ctxt.tstack == m_ctxt.bstack );
+    }
+    body
+    {
+        m_state = State.HOLD;
+        initStack();
+        m_unhandled = null;
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // General Properties
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * A fiber may occupy one of three states: HOLD, EXEC, and TERM.  The HOLD
+     * state applies to any fiber that is suspended and ready to be called.
+     * The EXEC state will be set for any fiber that is currently executing.
+     * And the TERM state is set when a fiber terminates.  Once a fiber
+     * terminates, it must be reset before it may be called again.
+     */
+    enum State
+    {
+        HOLD,   ///
+        EXEC,   ///
+        TERM    ///
+    }
+
+
+    /**
+     * Gets the current state of this fiber.
+     *
+     * Returns:
+     *  The state of this fiber as an enumerated value.
+     */
+    final State state()
+    {
+        return m_state;
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Actions on Calling Fiber
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Forces a context switch to occur away from the calling fiber.
+     */
+    static void yield()
+    {
+        Fiber   cur = getThis();
+        assert( cur, "Fiber.yield() called with no active fiber" );
+        assert( cur.m_state == State.EXEC );
+
+        static if( is( ucontext_t ) )
+          cur.m_ucur = &cur.m_utxt;
+
+        cur.m_state = State.HOLD;
+        cur.switchOut();
+        cur.m_state = State.EXEC;
+    }
+
+
+    /**
+     * Forces a context switch to occur away from the calling fiber and then
+     * throws obj in the calling fiber.
+     *
+     * Params:
+     *  obj = The object to throw.
+     *
+     * In:
+     *  obj must not be null.
+     */
+    static void yieldAndThrow( Object obj )
+    in
+    {
+        assert( obj );
+    }
+    body
+    {
+        Fiber   cur = getThis();
+        assert( cur, "Fiber.yield() called with no active fiber" );
+        assert( cur.m_state == State.EXEC );
+
+        static if( is( ucontext_t ) )
+          cur.m_ucur = &cur.m_utxt;
+
+        cur.m_unhandled = obj;
+        cur.m_state = State.HOLD;
+        cur.switchOut();
+        cur.m_state = State.EXEC;
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Fiber Accessors
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Provides a reference to the calling fiber or null if no fiber is
+     * currently active.
+     *
+     * Returns:
+     *  The fiber object representing the calling fiber or null if no fiber
+     *  is currently active.  The result of deleting this object is undefined.
+     */
+    static Fiber getThis()
+    {
+        version( Windows )
+        {
+            return cast(Fiber) TlsGetValue( sm_this );
+        }
+        else version( Posix )
+        {
+            return cast(Fiber) pthread_getspecific( sm_this );
+        }
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Static Initialization
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    static this()
+    {
+        version( Windows )
+        {
+            sm_this = TlsAlloc();
+            assert( sm_this != TLS_OUT_OF_INDEXES );
+        }
+        else version( Posix )
+        {
+            int status;
+
+            status = pthread_key_create( &sm_this, null );
+            assert( status == 0 );
+
+          static if( is( ucontext_t ) )
+          {
+            status = getcontext( &sm_utxt );
+            assert( status == 0 );
+          }
+        }
+    }
+
+
+private:
+    //
+    // Initializes a fiber object which has no associated executable function.
+    //
+    this()
+    {
+        m_call = Call.NO;
+    }
+
+
+    //
+    // Fiber entry point.  Invokes the function or delegate passed on
+    // construction (if any).
+    //
+    final void run()
+    {
+        switch( m_call )
+        {
+        case Call.FN:
+            m_fn();
+            break;
+        case Call.DG:
+            m_dg();
+            break;
+        default:
+            break;
+        }
+    }
+
+
+private:
+    //
+    // The type of routine passed on fiber construction.
+    //
+    enum Call
+    {
+        NO,
+        FN,
+        DG
+    }
+
+
+    //
+    // Standard fiber data
+    //
+    Call                m_call;
+    union
+    {
+        void function() m_fn;
+        void delegate() m_dg;
+    }
+    bool                m_isRunning;
+    Object              m_unhandled;
+    State               m_state;
+
+
+private:
+    ///////////////////////////////////////////////////////////////////////////
+    // Stack Management
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    //
+    // Allocate a new stack for this fiber.
+    //
+    final void allocStack( size_t sz )
+    in
+    {
+        assert( !m_pmem && !m_ctxt );
+    }
+    body
+    {
+        // adjust alloc size to a multiple of PAGESIZE
+        sz += PAGESIZE - 1;
+        sz -= sz % PAGESIZE;
+
+        // NOTE: This instance of Thread.Context is dynamic so Fiber objects
+        //       can be collected by the GC so long as no user level references
+        //       to the object exist.  If m_ctxt were not dynamic then its
+        //       presence in the global context list would be enough to keep
+        //       this object alive indefinitely.  An alternative to allocating
+        //       room for this struct explicitly would be to mash it into the
+        //       base of the stack being allocated below.  However, doing so
+        //       requires too much special logic to be worthwhile.
+        m_ctxt = new Thread.Context;
+
+        static if( is( typeof( VirtualAlloc ) ) )
+        {
+            // reserve memory for stack
+            m_pmem = VirtualAlloc( null,
+                                   sz + PAGESIZE,
+                                   MEM_RESERVE,
+                                   PAGE_NOACCESS );
+            if( !m_pmem )
+            {
+                throw new FiberException( "Unable to reserve memory for stack" );
+            }
+
+            version( StackGrowsDown )
+            {
+                void* stack = m_pmem + PAGESIZE;
+                void* guard = m_pmem;
+                void* pbase = stack + sz;
+            }
+            else
+            {
+                void* stack = m_pmem;
+                void* guard = m_pmem + sz;
+                void* pbase = stack;
+            }
+
+            // allocate reserved stack segment
+            stack = VirtualAlloc( stack,
+                                  sz,
+                                  MEM_COMMIT,
+                                  PAGE_READWRITE );
+            if( !stack )
+            {
+                throw new FiberException( "Unable to allocate memory for stack" );
+            }
+
+            // allocate reserved guard page
+            guard = VirtualAlloc( guard,
+                                  PAGESIZE,
+                                  MEM_COMMIT,
+                                  PAGE_READWRITE | PAGE_GUARD );
+            if( !guard )
+            {
+                throw new FiberException( "Unable to create guard page for stack" );
+            }
+
+            m_ctxt.bstack = pbase;
+            m_ctxt.tstack = pbase;
+            m_size = sz;
+        }
+        else
+        {   static if( is( typeof( mmap ) ) )
+            {
+                m_pmem = mmap( null,
+                               sz,
+                               PROT_READ | PROT_WRITE,
+                               MAP_PRIVATE | MAP_ANON,
+                               -1,
+                               0 );
+                if( m_pmem == MAP_FAILED )
+                    m_pmem = null;
+            }
+            else static if( is( typeof( valloc ) ) )
+            {
+                m_pmem = valloc( sz );
+            }
+            else static if( is( typeof( malloc ) ) )
+            {
+                m_pmem = malloc( sz );
+            }
+            else
+            {
+                m_pmem = null;
+            }
+
+            if( !m_pmem )
+            {
+                throw new FiberException( "Unable to allocate memory for stack" );
+            }
+
+            version( StackGrowsDown )
+            {
+                m_ctxt.bstack = m_pmem + sz;
+                m_ctxt.tstack = m_pmem + sz;
+            }
+            else
+            {
+                m_ctxt.bstack = m_pmem;
+                m_ctxt.tstack = m_pmem;
+            }
+            m_size = sz;
+        }
+
+        Thread.add( m_ctxt );
+    }
+
+
+    //
+    // Free this fiber's stack.
+    //
+    final void freeStack()
+    in
+    {
+        assert( m_pmem && m_ctxt );
+    }
+    body
+    {
+        // NOTE: Since this routine is only ever expected to be called from
+        //       the dtor, pointers to freed data are not set to null.
+
+        // NOTE: m_ctxt is guaranteed to be alive because it is held in the
+        //       global context list.
+        Thread.remove( m_ctxt );
+
+        static if( is( typeof( VirtualAlloc ) ) )
+        {
+            VirtualFree( m_pmem, 0, MEM_RELEASE );
+        }
+        else static if( is( typeof( mmap ) ) )
+        {
+            munmap( m_pmem, m_size );
+        }
+        else static if( is( typeof( valloc ) ) )
+        {
+            free( m_pmem );
+        }
+        else static if( is( typeof( malloc ) ) )
+        {
+            free( m_pmem );
+        }
+        delete m_ctxt;
+    }
+
+
+    //
+    // Initialize the allocated stack.
+    //
+    final void initStack()
+    in
+    {
+        assert( m_ctxt.tstack && m_ctxt.tstack == m_ctxt.bstack );
+        assert( cast(size_t) m_ctxt.bstack % (void*).sizeof == 0 );
+    }
+    body
+    {
+        void* pstack = m_ctxt.tstack;
+        scope( exit )  m_ctxt.tstack = pstack;
+
+        void push( size_t val )
+        {
+            version( StackGrowsDown )
+            {
+                pstack -= size_t.sizeof;
+                *(cast(size_t*) pstack) = val;
+            }
+            else
+            {
+                pstack += size_t.sizeof;
+                *(cast(size_t*) pstack) = val;
+            }
+        }
+
+        // NOTE: On OS X the stack must be 16-byte aligned according to the
+        // IA-32 call spec.
+        version( OSX )
+        {
+            version( StackGrowsDown )
+            {
+                pstack = cast(void*)(cast(uint)(pstack) - (cast(uint)(pstack) & 0x0F));
+            }
+            else
+            {
+                pstack = cast(void*)(cast(uint)(pstack) + (cast(uint)(pstack) & 0x0F));
+            }
+        }
+
+        version( AsmX86_Win32 )
+        {
+            push( cast(size_t) &fiber_entryPoint );                 // EIP
+            push( 0xFFFFFFFF );                                     // EBP
+            push( 0x00000000 );                                     // EAX
+            push( 0xFFFFFFFF );                                     // FS:[0]
+            version( StackGrowsDown )
+            {
+                push( cast(size_t) m_ctxt.bstack );                 // FS:[4]
+                push( cast(size_t) m_ctxt.bstack - m_size );        // FS:[8]
+            }
+            else
+            {
+                push( cast(size_t) m_ctxt.bstack );                 // FS:[4]
+                push( cast(size_t) m_ctxt.bstack + m_size );        // FS:[8]
+            }
+            push( 0x00000000 );                                     // EBX
+            push( 0x00000000 );                                     // ESI
+            push( 0x00000000 );                                     // EDI
+        }
+        else version( AsmX86_Posix )
+        {
+            push( 0x00000000 );                                     // Pad stack for OSX
+            push( cast(size_t) &fiber_entryPoint );                 // EIP
+            push( 0x00000000 );                                     // EBP
+            push( 0x00000000 );                                     // EAX
+            push( 0x00000000 );                                     // EBX
+            push( 0x00000000 );                                     // ESI
+            push( 0x00000000 );                                     // EDI
+        }
+        else version( AsmPPC_Posix )
+        {
+            version( StackGrowsDown )
+            {
+                pstack -= int.sizeof * 5;
+            }
+            else
+            {
+                pstack += int.sizeof * 5;
+            }
+
+            push( cast(size_t) &fiber_entryPoint );     // link register
+            push( 0x00000000 );                         // control register
+            push( 0x00000000 );                         // old stack pointer
+
+            // GPR values
+            version( StackGrowsDown )
+            {
+                pstack -= int.sizeof * 20;
+            }
+            else
+            {
+                pstack += int.sizeof * 20;
+            }
+
+            assert( cast(uint) pstack & 0x0f == 0 );
+        }
+        else static if( is( ucontext_t ) )
+        {
+            getcontext( &m_utxt );
+            m_utxt.uc_stack.ss_sp   = m_ctxt.bstack;
+            m_utxt.uc_stack.ss_size = m_size;
+            makecontext( &m_utxt, &fiber_entryPoint, 0 );
+            // NOTE: If ucontext is being used then the top of the stack will
+            //       be a pointer to the ucontext_t struct for that fiber.
+            push( cast(size_t) &m_utxt );
+        }
+    }
+
+
+    Thread.Context* m_ctxt;
+    size_t          m_size;
+    void*           m_pmem;
+
+    static if( is( ucontext_t ) )
+    {
+        // NOTE: The static ucontext instance is used to represent the context
+        //       of the main application thread.
+        static ucontext_t   sm_utxt = void;
+        ucontext_t          m_utxt  = void;
+        ucontext_t*         m_ucur  = null;
+    }
+
+
+private:
+    ///////////////////////////////////////////////////////////////////////////
+    // Storage of Active Fiber
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    //
+    // Sets a thread-local reference to the current fiber object.
+    //
+    static void setThis( Fiber f )
+    {
+        version( Windows )
+        {
+            TlsSetValue( sm_this, cast(void*) f );
+        }
+        else version( Posix )
+        {
+            pthread_setspecific( sm_this, cast(void*) f );
+        }
+    }
+
+
+    __gshared Thread.TLSKey    sm_this;
+
+
+private:
+    ///////////////////////////////////////////////////////////////////////////
+    // Context Switching
+    ///////////////////////////////////////////////////////////////////////////
+
+
+    //
+    // Switches into the stack held by this fiber.
+    //
+    final void switchIn()
+    {
+        Thread  tobj = Thread.getThis();
+        void**  oldp = &tobj.m_curr.tstack;
+        void*   newp = m_ctxt.tstack;
+
+        // NOTE: The order of operations here is very important.  The current
+        //       stack top must be stored before m_lock is set, and pushContext
+        //       must not be called until after m_lock is set.  This process
+        //       is intended to prevent a race condition with the suspend
+        //       mechanism used for garbage collection.  If it is not followed,
+        //       a badly timed collection could cause the GC to scan from the
+        //       bottom of one stack to the top of another, or to miss scanning
+        //       a stack that still contains valid data.  The old stack pointer
+        //       oldp will be set again before the context switch to guarantee
+        //       that it points to exactly the correct stack location so the
+        //       successive pop operations will succeed.
+        *oldp = getStackTop();
+        volatile tobj.m_lock = true;
+        tobj.pushContext( m_ctxt );
+
+        fiber_switchContext( oldp, newp );
+
+        // NOTE: As above, these operations must be performed in a strict order
+        //       to prevent Bad Things from happening.
+        tobj.popContext();
+        volatile tobj.m_lock = false;
+        tobj.m_curr.tstack = tobj.m_curr.bstack;
+    }
+
+
+    //
+    // Switches out of the current stack and into the enclosing stack.
+    //
+    final void switchOut()
+    {
+        Thread  tobj = Thread.getThis();
+        void**  oldp = &m_ctxt.tstack;
+        void*   newp = tobj.m_curr.within.tstack;
+
+        // NOTE: The order of operations here is very important.  The current
+        //       stack top must be stored before m_lock is set, and pushContext
+        //       must not be called until after m_lock is set.  This process
+        //       is intended to prevent a race condition with the suspend
+        //       mechanism used for garbage collection.  If it is not followed,
+        //       a badly timed collection could cause the GC to scan from the
+        //       bottom of one stack to the top of another, or to miss scanning
+        //       a stack that still contains valid data.  The old stack pointer
+        //       oldp will be set again before the context switch to guarantee
+        //       that it points to exactly the correct stack location so the
+        //       successive pop operations will succeed.
+        *oldp = getStackTop();
+        volatile tobj.m_lock = true;
+
+        fiber_switchContext( oldp, newp );
+
+        // NOTE: As above, these operations must be performed in a strict order
+        //       to prevent Bad Things from happening.
+        volatile tobj.m_lock = false;
+        tobj.m_curr.tstack = tobj.m_curr.bstack;
+    }
+}
+
+version (OSX)
+{
+    /* The Mach-O object file format does not allow for thread local storage
+     * declarations. So, instead we roll our own by putting tls into
+     * the sections __tlsdata and __tlscoal_nt.
+     */
+
+    extern (D)
+    void* ___tls_get_addr(void* p)
+    {
+	return p;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/threadasm.S	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,143 @@
+/**
+ * Support code for mutithreading.
+ *
+ * Copyright: Copyright Mikola Lysenko 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Mikola Lysenko
+ *
+ *          Copyright Mikola Lysenko 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/************************************************************************************
+ * POWER PC ASM BITS
+ ************************************************************************************/
+#if defined( __ppc__ ) || defined( __PPC__ ) || defined( __powerpc__ )
+
+
+/**
+ * Performs a context switch.
+ *
+ * r3 - old context pointer
+ * r4 - new context pointer
+ *
+ */
+.text
+.align 2
+.globl _fiber_switchContext
+_fiber_switchContext:
+
+    /* Save linkage area */
+    mflr        r0
+    mfcr        r5
+    stw     r0, 8(r1)
+    stw     r5, 4(r1)
+
+    /* Save GPRs */
+    stw     r11, (-1 * 4)(r1)
+    stw     r13, (-2 * 4)(r1)
+    stw     r14, (-3 * 4)(r1)
+    stw     r15, (-4 * 4)(r1)
+    stw     r16, (-5 * 4)(r1)
+    stw     r17, (-6 * 4)(r1)
+    stw     r18, (-7 * 4)(r1)
+    stw     r19, (-8 * 4)(r1)
+    stw     r20, (-9 * 4)(r1)
+    stw     r21, (-10 * 4)(r1)
+    stw     r22, (-11 * 4)(r1)
+    stw     r23, (-12 * 4)(r1)
+    stw     r24, (-13 * 4)(r1)
+    stw     r25, (-14 * 4)(r1)
+    stw     r26, (-15 * 4)(r1)
+    stw     r27, (-16 * 4)(r1)
+    stw     r28, (-17 * 4)(r1)
+    stw     r29, (-18 * 4)(r1)
+    stw     r30, (-19 * 4)(r1)
+    stwu    r31, (-20 * 4)(r1)
+
+    /* We update the stack pointer here, since we do not want the GC to
+       scan the floating point registers. */
+
+    /* Save FPRs */
+    stfd    f14, (-1 * 8)(r1)
+    stfd    f15, (-2 * 8)(r1)
+    stfd    f16, (-3 * 8)(r1)
+    stfd    f17, (-4 * 8)(r1)
+    stfd    f18, (-5 * 8)(r1)
+    stfd    f19, (-6 * 8)(r1)
+    stfd    f20, (-7 * 8)(r1)
+    stfd    f21, (-8 * 8)(r1)
+    stfd    f22, (-9 * 8)(r1)
+    stfd    f23, (-10 * 8)(r1)
+    stfd    f24, (-11 * 8)(r1)
+    stfd    f25, (-12 * 8)(r1)
+    stfd    f26, (-13 * 8)(r1)
+    stfd    f27, (-14 * 8)(r1)
+    stfd    f28, (-15 * 8)(r1)
+    stfd    f29, (-16 * 8)(r1)
+    stfd    f30, (-17 * 8)(r1)
+    stfd    f31, (-18 * 8)(r1)
+
+    /* Update the old stack pointer */
+    stw     r1, 0(r3)
+
+    /* Set new stack pointer */
+    addi        r1, r4, 20 * 4
+
+    /* Restore linkage area */
+    lwz     r0, 8(r1)
+    lwz     r5, 4(r1)
+
+    /* Restore GPRs */
+    lwz     r11, (-1 * 4)(r1)
+    lwz     r13, (-2 * 4)(r1)
+    lwz     r14, (-3 * 4)(r1)
+    lwz     r15, (-4 * 4)(r1)
+    lwz     r16, (-5 * 4)(r1)
+    lwz     r17, (-6 * 4)(r1)
+    lwz     r18, (-7 * 4)(r1)
+    lwz     r19, (-8 * 4)(r1)
+    lwz     r20, (-9 * 4)(r1)
+    lwz     r21, (-10 * 4)(r1)
+    lwz     r22, (-11 * 4)(r1)
+    lwz     r23, (-12 * 4)(r1)
+    lwz     r24, (-13 * 4)(r1)
+    lwz     r25, (-14 * 4)(r1)
+    lwz     r26, (-15 * 4)(r1)
+    lwz     r27, (-16 * 4)(r1)
+    lwz     r28, (-17 * 4)(r1)
+    lwz     r29, (-18 * 4)(r1)
+    lwz     r30, (-19 * 4)(r1)
+    lwz     r31, (-20 * 4)(r1)
+
+
+    /* Restore FPRs */
+    lfd     f14, (-1 * 8)(r4)
+    lfd     f15, (-2 * 8)(r4)
+    lfd     f16, (-3 * 8)(r4)
+    lfd     f17, (-4 * 8)(r4)
+    lfd     f18, (-5 * 8)(r4)
+    lfd     f19, (-6 * 8)(r4)
+    lfd     f20, (-7 * 8)(r4)
+    lfd     f21, (-8 * 8)(r4)
+    lfd     f22, (-9 * 8)(r4)
+    lfd     f23, (-10 * 8)(r4)
+    lfd     f24, (-11 * 8)(r4)
+    lfd     f25, (-12 * 8)(r4)
+    lfd     f26, (-13 * 8)(r4)
+    lfd     f27, (-14 * 8)(r4)
+    lfd     f28, (-15 * 8)(r4)
+    lfd     f29, (-16 * 8)(r4)
+    lfd     f30, (-17 * 8)(r4)
+    lfd     f31, (-18 * 8)(r4)
+
+    /* Set condition and link register */
+    mtcr        r5
+    mtlr        r0
+
+    /* Return and switch context */
+    blr
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/vararg.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,81 @@
+/**
+ * The vararg module is intended to facilitate vararg manipulation in D.
+ * It should be interface compatible with the C module "stdarg," and the
+ * two modules may share a common implementation if possible (as is done
+ * here). 
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Hauke Duden
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.vararg;
+
+
+/**
+ * The base vararg list type.
+ */
+alias void* va_list;
+
+
+/**
+ * This function initializes the supplied argument pointer for subsequent
+ * use by va_arg and va_end.
+ *
+ * Params:
+ *  ap      = The argument pointer to initialize.
+ *  paramn  = The identifier of the rightmost parameter in the function
+ *            parameter list.
+ */
+void va_start(T) ( out va_list ap, inout T parmn )
+{
+    ap = cast(va_list) ( cast(void*) &parmn + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) );
+}
+
+/**
+ * This function returns the next argument in the sequence referenced by
+ * the supplied argument pointer.  The argument pointer will be adjusted
+ * to point to the next arggument in the sequence.
+ *
+ * Params:
+ *  ap  = The argument pointer.
+ *
+ * Returns:
+ *  The next argument in the sequence.  The result is undefined if ap
+ *  does not point to a valid argument.
+ */
+T va_arg(T) ( inout va_list ap )
+{
+    T arg = *cast(T*) ap;
+    ap = cast(va_list) ( cast(void*) ap + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) );
+    return arg;
+}
+
+/**
+ * This function cleans up any resources allocated by va_start.  It is
+ * currently a no-op and exists mostly for syntax compatibility with
+ * the variadric argument functions for C.
+ *
+ * Params:
+ *  ap  = The argument pointer.
+ */
+void va_end( va_list ap )
+{
+
+}
+
+
+/**
+ * This function copied the argument pointer src to dst.
+ *
+ * Params:
+ *  src = The source pointer.
+ *  dst = The destination pointer.
+ */
+void va_copy( out va_list dst, va_list src )
+{
+    dst = src;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/posix.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,81 @@
+# Makefile to build the D runtime library core components for Posix
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR=../../lib
+DOCDIR=../../doc
+IMPDIR=../../import
+LIBBASENAME=libdruntime-core.a
+MODULES=bitop exception memory runtime thread vararg \
+	$(addprefix sync/,barrier condition config exception mutex rwmutex semaphore)
+BUILDS=debug release unittest
+
+# Symbols
+
+DMD=dmd
+CLC=ar rsv
+DOCFLAGS=-version=DDoc
+DFLAGS_release=-d -release -O -inline -w
+DFLAGS_debug=-d -g -w
+DFLAGS_unittest=$(DFLAGS_release) -unittest
+CFLAGS_release= -O
+CFLAGS_debug= -g
+CFLAGS_unittest=$(CFLAGS_release)
+
+# Derived symbols
+
+C_SRCS=core/stdc/errno.c #core/threadasm.S
+C_OBJS=errno.o threadasm.o
+AS_OBJS=$(addsuffix .o,$(basename $(AS_SRCS)))
+D_SRCS=$(addsuffix .d,$(addprefix core/,$(MODULES))) \
+	$(addsuffix .d,$(addprefix $(IMPDIR)/core/stdc/,math stdarg stdio wchar_)) \
+	$(addsuffix .d,$(addprefix $(IMPDIR)/core/sys/posix/,netinet/in_ sys/select sys/socket sys/stat sys/wait))
+ALL_OBJS_O=$(addsuffix .o,$(addprefix core/,$(MODULES))) \
+	$(addsuffix .o,$(addprefix $(IMPDIR)/core/stdc/,math stdarg stdio wchar_)) \
+	$(addsuffix .o,$(addprefix $(IMPDIR)/core/sys/posix/,netinet/in_ sys/select sys/socket sys/stat sys/wait)) \
+	$(AS_OBJS) $(C_OBJS)
+DOCS=$(addsuffix .html,$(addprefix $(DOCDIR)/core/,$(MODULES)))
+IMPORTS=$(addsuffix .di,$(addprefix $(IMPDIR)/core/,$(MODULES)))
+ALLLIBS=$(addsuffix /$(LIBBASENAME),$(addprefix $(LIBDIR)/,$(BUILDS)))
+
+# Patterns
+
+$(LIBDIR)/%/$(LIBBASENAME) : $(D_SRCS) $(C_SRCS)
+	$(CC) -c $(CFLAGS_$*) $(C_SRCS)
+ifeq ($(DMD),ldc2 -vv)
+	$(DMD) $(DFLAGS_$*) -of$@ $(D_SRCS)
+	$(CLC) $@ $(ALL_OBJS_O)
+else
+	$(DMD) $(DFLAGS_$*) -lib -of$@ $(D_SRCS) $(C_OBJS)
+endif
+	rm $(C_OBJS)
+
+$(DOCDIR)/%.html : %.d
+	$(DMD) -c -d -o- -Df$@ $<
+
+$(IMPDIR)/%.di : %.d
+	$(DMD) -c -d -o- -Hf$@ $<
+
+# Rulez
+
+all : $(BUILDS) doc
+
+debug : $(LIBDIR)/debug/$(LIBBASENAME) $(IMPORTS)
+release : $(LIBDIR)/release/$(LIBBASENAME) $(IMPORTS)
+unittest : $(LIBDIR)/unittest/$(LIBBASENAME) $(IMPORTS)
+doc : $(DOCS)
+
+clean :
+	rm -f $(IMPORTS) $(DOCS) $(ALLLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/win32.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,226 @@
+# Makefile to build the D runtime library core components for Posix
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR=..\..\lib
+DOCDIR=..\..\doc
+IMPDIR=..\..\import
+LIBBASENAME=druntime_core.lib
+#MODULES=bitop exception memory runtime thread vararg \
+#	$(addprefix sync/,barrier condition config exception mutex rwmutex semaphore)
+BUILDS=debug release unittest
+
+# Symbols
+
+CC=dmc
+DMD=dmd
+DOCFLAGS=-version=DDoc
+DFLAGS_release=-d -release -O -inline -w -nofloat
+DFLAGS_debug=-d -g -w -nofloat
+DFLAGS_unittest=$(DFLAGS_release) -unittest
+CFLAGS_release=-mn -6 -r
+CFLAGS_debug=-g -mn -6 -r
+CFLAGS_unittest=$(CFLAGS_release)
+
+# Derived symbols
+
+C_SRCS=core\stdc\errno.c
+
+C_OBJS=errno.obj
+
+D_SRCS=\
+	core\bitop.d \
+	core\exception.d \
+	core\memory.d \
+	core\runtime.d \
+	core\thread.d \
+	core\vararg.d \
+	\
+	core\sync\barrier.d \
+	core\sync\condition.d \
+	core\sync\config.d \
+	core\sync\exception.d \
+	core\sync\mutex.d \
+	core\sync\rwmutex.d \
+	core\sync\semaphore.d \
+	\
+	$(IMPDIR)\core\stdc\math.d \
+	$(IMPDIR)\core\stdc\stdarg.d \
+	$(IMPDIR)\core\stdc\stdio.d \
+	$(IMPDIR)\core\stdc\wchar_.d \
+	\
+	$(IMPDIR)\core\sys\windows\windows.d
+
+DOCS=\
+	$(DOCDIR)\core\bitop.html \
+	$(DOCDIR)\core\exception.html \
+	$(DOCDIR)\core\memory.html \
+	$(DOCDIR)\core\runtime.html \
+	$(DOCDIR)\core\thread.html \
+	$(DOCDIR)\core\vararg.html \
+	\
+	$(DOCDIR)\core\sync\barrier.html \
+	$(DOCDIR)\core\sync\condition.html \
+	$(DOCDIR)\core\sync\config.html \
+	$(DOCDIR)\core\sync\exception.html \
+	$(DOCDIR)\core\sync\mutex.html \
+	$(DOCDIR)\core\sync\rwmutex.html \
+	$(DOCDIR)\core\sync\semaphore.html
+
+IMPORTS=\
+	$(IMPDIR)\core\exception.di \
+	$(IMPDIR)\core\memory.di \
+	$(IMPDIR)\core\runtime.di \
+	$(IMPDIR)\core\thread.di \
+	$(IMPDIR)\core\vararg.di \
+	\
+	$(IMPDIR)\core\sync\barrier.di \
+	$(IMPDIR)\core\sync\condition.di \
+	$(IMPDIR)\core\sync\config.di \
+	$(IMPDIR)\core\sync\exception.di \
+	$(IMPDIR)\core\sync\mutex.di \
+	$(IMPDIR)\core\sync\rwmutex.di \
+	$(IMPDIR)\core\sync\semaphore.di
+	# bitop.di is already published
+
+ALLLIBS=\
+	$(LIBDIR)\debug\$(LIBBASENAME) \
+	$(LIBDIR)\release\$(LIBBASENAME) \
+	$(LIBDIR)\unittest\$(LIBBASENAME)
+
+# Patterns
+
+#$(LIBDIR)\%\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS)
+#	$(CC) -c $(CFLAGS_$*) $(C_SRCS)
+#	$(DMD) $(DFLAGS_$*) -lib -of$@ $(D_SRCS) $(C_OBJS)
+#	del $(C_OBJS)
+
+#$(DOCDIR)\%.html : %.d
+#	$(DMD) -c -d -o- -Df$@ $<
+
+#$(IMPDIR)\%.di : %.d
+#	$(DMD) -c -d -o- -Hf$@ $<
+
+# Patterns - debug
+
+$(LIBDIR)\debug\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS)
+	$(CC) -c $(CFLAGS_debug) $(C_SRCS)
+	$(DMD) $(DFLAGS_debug) -lib -of$@ $(D_SRCS) $(C_OBJS)
+	del $(C_OBJS)
+
+# Patterns - release
+
+$(LIBDIR)\release\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS)
+	$(CC) -c $(CFLAGS_release) $(C_SRCS)
+	$(DMD) $(DFLAGS_release) -lib -of$@ $(D_SRCS) $(C_OBJS)
+	del $(C_OBJS)
+
+# Patterns - unittest
+
+$(LIBDIR)\unittest\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS)
+	$(CC) -c $(CFLAGS_unittest) $(C_SRCS)
+	$(DMD) $(DFLAGS_unittest) -lib -of$@ $(D_SRCS) $(C_OBJS)
+	del $(C_OBJS)
+
+# Patterns - docs
+
+$(DOCDIR)\core\bitop.html : core\bitop.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\exception.html : core\exception.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\memory.html : core\memory.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\runtime.html : core\runtime.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\thread.html : core\thread.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\vararg.html : core\vararg.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\sync\barrier.html : core\sync\barrier.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\sync\condition.html : core\sync\condition.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\sync\config.html : core\sync\config.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\sync\exception.html : core\sync\exception.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\sync\mutex.html : core\sync\mutex.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\sync\rwmutex.html : core\sync\rwmutex.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+$(DOCDIR)\core\sync\semaphore.html : core\sync\semaphore.d
+	$(DMD) -c -d -o- -Df$@ $**
+
+# Patterns - imports
+
+$(IMPDIR)\core\exception.di : core\exception.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+$(IMPDIR)\core\memory.di : core\memory.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+$(IMPDIR)\core\runtime.di : core\runtime.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+$(IMPDIR)\core\thread.di : core\thread.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+$(IMPDIR)\core\vararg.di : core\vararg.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+$(IMPDIR)\core\sync\barrier.di : core\sync\barrier.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+$(IMPDIR)\core\sync\condition.di : core\sync\condition.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+$(IMPDIR)\core\sync\config.di : core\sync\config.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+$(IMPDIR)\core\sync\exception.di : core\sync\exception.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+$(IMPDIR)\core\sync\mutex.di : core\sync\mutex.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+$(IMPDIR)\core\sync\rwmutex.di : core\sync\rwmutex.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+$(IMPDIR)\core\sync\semaphore.di : core\sync\semaphore.d
+	$(DMD) -c -d -o- -Hf$@ $**
+
+# Rulez
+
+all : $(BUILDS) doc
+
+debug : $(LIBDIR)\debug\$(LIBBASENAME) $(IMPORTS)
+release : $(LIBDIR)\release\$(LIBBASENAME) $(IMPORTS)
+unittest : $(LIBDIR)\unittest\$(LIBBASENAME) $(IMPORTS)
+doc : $(DOCS)
+
+clean :
+	del $(IMPORTS) $(DOCS) $(ALLLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/aApply.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,386 @@
+/**
+ * This code handles decoding UTF strings for foreach loops.  There are 6
+ * combinations of conversions between char, wchar, and dchar, and 2 of each
+ * of those.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.aApply;
+
+private import rt.util.utf;
+
+/**********************************************
+ */
+
+// dg is D, but _aApplycd() is C
+extern (D) typedef int delegate(void *) dg_t;
+
+extern (C) int _aApplycd1(char[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycd1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+
+        d = aa[i];
+        if (d & 0x80)
+            d = decode(aa, i);
+        else
+            i++;
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywd1(wchar[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywd1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+
+        d = aa[i];
+        if (d & ~0x7F)
+            d = decode(aa, i);
+        else
+            i++;
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplycw1(char[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycw1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+        wchar w;
+
+        w = aa[i];
+        if (w & 0x80)
+        {   d = decode(aa, i);
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+                w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(cast(void *)&w);
+                if (result)
+                    break;
+                w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        else
+            i++;
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywc1(wchar[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywc1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+        wchar w;
+        char c;
+
+        w = aa[i];
+        if (w & ~0x7F)
+        {
+            char[4] buf;
+
+            d = decode(aa, i);
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)w;
+            i++;
+        }
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydc1(dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
+    foreach (dchar d; aa)
+    {
+        char c;
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {
+            c = cast(char)d;
+        }
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydw1(dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
+    foreach (dchar d; aa)
+    {
+        wchar w;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+            w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(cast(void *)&w);
+            if (result)
+                break;
+            w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+
+/****************************************************************************/
+
+// dg is D, but _aApplycd2() is C
+extern (D) typedef int delegate(void *, void *) dg2_t;
+
+extern (C) int _aApplycd2(char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycd2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+
+        d = aa[i];
+        if (d & 0x80)
+        {
+            n = i;
+            d = decode(aa, n);
+            n -= i;
+        }
+        else
+            n = 1;
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywd2(wchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywd2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+
+        d = aa[i];
+        if (d & ~0x7F)
+        {
+            n = i;
+            d = decode(aa, n);
+            n -= i;
+        }
+        else
+            n = 1;
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplycw2(char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycw2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+        wchar w;
+
+        w = aa[i];
+        if (w & 0x80)
+        {   n = i;
+            d = decode(aa, n);
+            n -= i;
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+                w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(&i, cast(void *)&w);
+                if (result)
+                    break;
+                w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        else
+            n = 1;
+        result = dg(&i, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywc2(wchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywc2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+        wchar w;
+        char c;
+
+        w = aa[i];
+        if (w & ~0x7F)
+        {
+            char[4] buf;
+
+            n = i;
+            d = decode(aa, n);
+            n -= i;
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)w;
+            n = 1;
+        }
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydc2(dchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplydc2(), len = %d\n", len);
+    for (i = 0; i < len; i++)
+    {   dchar d;
+        char c;
+
+        d = aa[i];
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)d;
+        }
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydw2(dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
+    foreach (size_t i, dchar d; aa)
+    {
+        wchar w;
+        auto j = i;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+            w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(&j, cast(void *)&w);
+            if (result)
+                break;
+            w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(&j, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/aApplyR.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,957 @@
+/**
+ * This code handles decoding UTF strings for foreach_reverse loops.  There are
+ * 6 combinations of conversions between char, wchar, and dchar, and 2 of each
+ * of those.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.aApplyR;
+
+/* This code handles decoding UTF strings for foreach_reverse loops.
+ * There are 6 combinations of conversions between char, wchar,
+ * and dchar, and 2 of each of those.
+ */
+
+private import rt.util.utf;
+
+/**********************************************/
+/* 1 argument versions */
+
+// dg is D, but _aApplyRcd() is C
+extern (D) typedef int delegate(void *) dg_t;
+
+extern (C) int _aApplyRcd1(in char[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d & 0x80)
+        {   char c = cast(char)d;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+        }
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcd1.unittest\n");
+
+    auto s = "hello"c[];
+    int i;
+
+    foreach_reverse(dchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(dchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == '\U00100456'); break;
+            case 2:     assert(d == '\u1234'); break;
+            case 3:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwd1(in wchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwd1.unittest\n");
+
+    auto s = "hello"w[];
+    int i;
+
+    foreach_reverse(dchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(dchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == '\U00100456'); break;
+            case 2:     assert(d == '\u1234'); break;
+            case 3:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRcw1(in char[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        wchar w;
+
+        i--;
+        w = aa[i];
+        if (w & 0x80)
+        {   char c = cast(char)w;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+                w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(cast(void *)&w);
+                if (result)
+                    break;
+                w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcw1.unittest\n");
+
+    auto s = "hello"c[];
+    int i;
+
+    foreach_reverse(wchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(wchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xDBC1); break;
+            case 2:     assert(d == 0xDC56); break;
+            case 3:     assert(d == 0x1234); break;
+            case 4:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwc1(in wchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        char c;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        c = cast(char)d;
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwc1.unittest\n");
+
+    auto s = "hello"w[];
+    int i;
+
+    foreach_reverse(char d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(char d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xF4); break;
+            case 2:     assert(d == 0x80); break;
+            case 3:     assert(d == 0x91); break;
+            case 4:     assert(d == 0x96); break;
+            case 5:     assert(d == 0xE1); break;
+            case 6:     assert(d == 0x88); break;
+            case 7:     assert(d == 0xB4); break;
+            case 8:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdc1(in dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0;)
+    {   dchar d = aa[--i];
+        char c;
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {
+            c = cast(char)d;
+        }
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdc1.unittest\n");
+
+    auto s = "hello"d[];
+    int i;
+
+    foreach_reverse(char d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(char d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xF4); break;
+            case 2:     assert(d == 0x80); break;
+            case 3:     assert(d == 0x91); break;
+            case 4:     assert(d == 0x96); break;
+            case 5:     assert(d == 0xE1); break;
+            case 6:     assert(d == 0x88); break;
+            case 7:     assert(d == 0xB4); break;
+            case 8:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdw1(in dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d = aa[--i];
+        wchar w;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+            w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(cast(void *)&w);
+            if (result)
+                break;
+            w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdw1.unittest\n");
+
+    auto s = "hello"d[];
+    int i;
+
+    foreach_reverse(wchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(wchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xDBC1); break;
+            case 2:     assert(d == 0xDC56); break;
+            case 3:     assert(d == 0x1234); break;
+            case 4:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
+
+
+/****************************************************************************/
+/* 2 argument versions */
+
+// dg is D, but _aApplyRcd2() is C
+extern (D) typedef int delegate(void *, void *) dg2_t;
+
+extern (C) int _aApplyRcd2(in char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplyRcd2(), len = %d\n", len);
+    for (i = len; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d & 0x80)
+        {   char c = cast(char)d;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+        }
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcd2.unittest\n");
+
+    auto s = "hello"c[];
+    int i;
+
+    foreach_reverse(k, dchar d; s)
+    {
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, dchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); assert(k == 8); break;
+            case 1:     assert(d == '\U00100456'); assert(k == 4); break;
+            case 2:     assert(d == '\u1234'); assert(k == 1); break;
+            case 3:     assert(d == 'a'); assert(k == 0); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwd2(in wchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwd2.unittest\n");
+
+    auto s = "hello"w[];
+    int i;
+
+    foreach_reverse(k, dchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, dchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 4); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == '\U00100456'); break;
+            case 2:     assert(k == 1); assert(d == '\u1234'); break;
+            case 3:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRcw2(in char[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        wchar w;
+
+        i--;
+        w = aa[i];
+        if (w & 0x80)
+        {   char c = cast(char)w;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+                w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(&i, cast(void *)&w);
+                if (result)
+                    break;
+                w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        result = dg(&i, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcw2.unittest\n");
+
+    auto s = "hello"c[];
+    int i;
+
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 8); assert(d == 'b'); break;
+            case 1:     assert(k == 4); assert(d == 0xDBC1); break;
+            case 2:     assert(k == 4); assert(d == 0xDC56); break;
+            case 3:     assert(k == 1); assert(d == 0x1234); break;
+            case 4:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwc2(in wchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        char c;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        c = cast(char)d;
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwc2.unittest\n");
+
+    auto s = "hello"w[];
+    int i;
+
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 4); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == 0xF4); break;
+            case 2:     assert(k == 2); assert(d == 0x80); break;
+            case 3:     assert(k == 2); assert(d == 0x91); break;
+            case 4:     assert(k == 2); assert(d == 0x96); break;
+            case 5:     assert(k == 1); assert(d == 0xE1); break;
+            case 6:     assert(k == 1); assert(d == 0x88); break;
+            case 7:     assert(k == 1); assert(d == 0xB4); break;
+            case 8:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdc2(in dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d = aa[--i];
+        char c;
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)d;
+        }
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdc2.unittest\n");
+
+    auto s = "hello"d[];
+    int i;
+
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 3); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == 0xF4); break;
+            case 2:     assert(k == 2); assert(d == 0x80); break;
+            case 3:     assert(k == 2); assert(d == 0x91); break;
+            case 4:     assert(k == 2); assert(d == 0x96); break;
+            case 5:     assert(k == 1); assert(d == 0xE1); break;
+            case 6:     assert(k == 1); assert(d == 0x88); break;
+            case 7:     assert(k == 1); assert(d == 0xB4); break;
+            case 8:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdw2(in dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d = aa[--i];
+        wchar w;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+            w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(&i, cast(void *)&w);
+            if (result)
+                break;
+            w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(&i, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdw2.unittest\n");
+
+    auto s = "hello"d[];
+    int i;
+
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 3); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == 0xDBC1); break;
+            case 2:     assert(k == 2); assert(d == 0xDC56); break;
+            case 3:     assert(k == 1); assert(d == 0x1234); break;
+            case 4:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/aaA.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,872 @@
+/**
+ * Implementation of associative arrays.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.aaA;
+
+private
+{
+    import core.stdc.stdarg;
+    import core.stdc.string;
+    import core.stdc.stdio;
+
+    enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001,
+        NO_SCAN  = 0b0000_0010,
+        NO_MOVE  = 0b0000_0100,
+        ALL_BITS = 0b1111_1111
+    }
+
+    extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
+    extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
+    extern (C) void  gc_free( void* p );
+}
+
+// Auto-rehash and pre-allocate - Dave Fladebo
+
+immutable size_t[] prime_list = [
+              97UL,            389UL,
+           1_543UL,          6_151UL,
+          24_593UL,         98_317UL,
+          393_241UL,      1_572_869UL,
+        6_291_469UL,     25_165_843UL,
+      100_663_319UL,    402_653_189UL,
+    1_610_612_741UL,  4_294_967_291UL,
+//  8_589_934_513UL, 17_179_869_143UL
+];
+
+/* This is the type of the return value for dynamic arrays.
+ * It should be a type that is returned in registers.
+ * Although DMD will return types of Array in registers,
+ * gcc will not, so we instead use a 'long'.
+ */
+alias long ArrayRet_t;
+
+struct Array
+{
+    size_t length;
+    void* ptr;
+}
+
+struct aaA
+{
+    aaA *left;
+    aaA *right;
+    hash_t hash;
+    /* key   */
+    /* value */
+}
+
+struct BB
+{
+    aaA*[] b;
+    size_t nodes;       // total number of aaA nodes
+    TypeInfo keyti;     // TODO: replace this with TypeInfo_AssociativeArray when available in _aaGet()
+}
+
+/* This is the type actually seen by the programmer, although
+ * it is completely opaque.
+ */
+
+struct AA
+{
+    BB* a;
+}
+
+/**********************************
+ * Align to next pointer boundary, so that
+ * GC won't be faced with misaligned pointers
+ * in value.
+ */
+
+size_t aligntsize(size_t tsize)
+{
+    // Is pointer alignment on the x64 4 bytes or 8?
+    return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
+}
+
+extern (C):
+
+/*************************************************
+ * Invariant for aa.
+ */
+
+/+
+void _aaInvAh(aaA*[] aa)
+{
+    for (size_t i = 0; i < aa.length; i++)
+    {
+        if (aa[i])
+            _aaInvAh_x(aa[i]);
+    }
+}
+
+private int _aaCmpAh_x(aaA *e1, aaA *e2)
+{   int c;
+
+    c = e1.hash - e2.hash;
+    if (c == 0)
+    {
+        c = e1.key.length - e2.key.length;
+        if (c == 0)
+            c = memcmp((char *)e1.key, (char *)e2.key, e1.key.length);
+    }
+    return c;
+}
+
+private void _aaInvAh_x(aaA *e)
+{
+    hash_t key_hash;
+    aaA *e1;
+    aaA *e2;
+
+    key_hash = getHash(e.key);
+    assert(key_hash == e.hash);
+
+    while (1)
+    {   int c;
+
+        e1 = e.left;
+        if (e1)
+        {
+            _aaInvAh_x(e1);             // ordinary recursion
+            do
+            {
+                c = _aaCmpAh_x(e1, e);
+                assert(c < 0);
+                e1 = e1.right;
+            } while (e1 != null);
+        }
+
+        e2 = e.right;
+        if (e2)
+        {
+            do
+            {
+                c = _aaCmpAh_x(e, e2);
+                assert(c < 0);
+                e2 = e2.left;
+            } while (e2 != null);
+            e = e.right;                // tail recursion
+        }
+        else
+            break;
+    }
+}
++/
+
+/****************************************************
+ * Determine number of entries in associative array.
+ */
+
+size_t _aaLen(AA aa)
+in
+{
+    //printf("_aaLen()+\n");
+    //_aaInv(aa);
+}
+out (result)
+{
+    size_t len = 0;
+
+    void _aaLen_x(aaA* ex)
+    {
+        auto e = ex;
+        len++;
+
+        while (1)
+        {
+            if (e.right)
+               _aaLen_x(e.right);
+            e = e.left;
+            if (!e)
+                break;
+            len++;
+        }
+    }
+
+    if (aa.a)
+    {
+        foreach (e; aa.a.b)
+        {
+            if (e)
+                _aaLen_x(e);
+        }
+    }
+    assert(len == result);
+
+    //printf("_aaLen()-\n");
+}
+body
+{
+    return aa.a ? aa.a.nodes : 0;
+}
+
+
+/*************************************************
+ * Get pointer to value in associative array indexed by key.
+ * Add entry for key if it is not already there.
+ */
+
+void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...)
+in
+{
+    assert(aa);
+}
+out (result)
+{
+    assert(result);
+    assert(aa.a);
+    assert(aa.a.b.length);
+    //assert(_aaInAh(*aa.a, key));
+}
+body
+{
+    auto pkey = cast(void *)(&valuesize + 1);
+    size_t i;
+    aaA *e;
+//printf("keyti = %p\n", keyti);
+//printf("aa = %p\n", aa);
+    auto keysize = aligntsize(keyti.tsize());
+
+    if (!aa.a)
+        aa.a = new BB();
+//printf("aa = %p\n", aa);
+//printf("aa.a = %p\n", aa.a);
+    aa.a.keyti = keyti;
+
+    if (!aa.a.b.length)
+    {
+        alias aaA *pa;
+        auto len = prime_list[0];
+
+        aa.a.b = new pa[len];
+    }
+
+    auto key_hash = keyti.getHash(pkey);
+    //printf("hash = %d\n", key_hash);
+    i = key_hash % aa.a.b.length;
+    auto pe = &aa.a.b[i];
+    while ((e = *pe) !is null)
+    {
+        if (key_hash == e.hash)
+        {
+            auto c = keyti.compare(pkey, e + 1);
+            if (c == 0)
+                goto Lret;
+            pe = (c < 0) ? &e.left : &e.right;
+        }
+        else
+            pe = (key_hash < e.hash) ? &e.left : &e.right;
+    }
+
+    // Not found, create new elem
+    //printf("create new one\n");
+    size_t size = aaA.sizeof + keysize + valuesize;
+    e = cast(aaA *) gc_calloc(size);
+    memcpy(e + 1, pkey, keysize);
+    e.hash = key_hash;
+    *pe = e;
+
+    auto nodes = ++aa.a.nodes;
+    //printf("length = %d, nodes = %d\n", aa.a.b.length, nodes);
+    if (nodes > aa.a.b.length * 4)
+    {
+	//printf("rehash\n");
+        _aaRehash(aa,keyti);
+    }
+
+Lret:
+    return cast(void *)(e + 1) + keysize;
+}
+
+
+/*************************************************
+ * Get pointer to value in associative array indexed by key.
+ * Returns null if it is not already there.
+ */
+
+void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...)
+{
+    //printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
+    if (!aa.a)
+        return null;
+
+    auto pkey = cast(void *)(&valuesize + 1);
+    auto keysize = aligntsize(keyti.tsize());
+    auto len = aa.a.b.length;
+
+    if (len)
+    {
+        auto key_hash = keyti.getHash(pkey);
+        //printf("hash = %d\n", key_hash);
+        size_t i = key_hash % len;
+        auto e = aa.a.b[i];
+        while (e !is null)
+        {
+            if (key_hash == e.hash)
+            {
+                auto c = keyti.compare(pkey, e + 1);
+            if (c == 0)
+                return cast(void *)(e + 1) + keysize;
+                e = (c < 0) ? e.left : e.right;
+            }
+            else
+                e = (key_hash < e.hash) ? e.left : e.right;
+        }
+    }
+    return null;    // not found, caller will throw exception
+}
+
+
+/*************************************************
+ * Determine if key is in aa.
+ * Returns:
+ *      null    not in aa
+ *      !=null  in aa, return pointer to value
+ */
+
+void* _aaIn(AA aa, TypeInfo keyti, ...)
+in
+{
+}
+out (result)
+{
+    //assert(result == 0 || result == 1);
+}
+body
+{
+    if (aa.a)
+    {
+        auto pkey = cast(void *)(&keyti + 1);
+
+        //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.a.length, cast(uint)aa.a.ptr);
+        auto len = aa.a.b.length;
+
+        if (len)
+        {
+            auto key_hash = keyti.getHash(pkey);
+            //printf("hash = %d\n", key_hash);
+            size_t i = key_hash % len;
+            auto e = aa.a.b[i];
+            while (e !is null)
+            {
+                if (key_hash == e.hash)
+                {
+                    auto c = keyti.compare(pkey, e + 1);
+                    if (c == 0)
+                        return cast(void *)(e + 1) + aligntsize(keyti.tsize());
+                    e = (c < 0) ? e.left : e.right;
+                }
+                else
+                    e = (key_hash < e.hash) ? e.left : e.right;
+            }
+        }
+    }
+
+    // Not found
+    return null;
+}
+
+/*************************************************
+ * Delete key entry in aa[].
+ * If key is not in aa[], do nothing.
+ */
+
+void _aaDel(AA aa, TypeInfo keyti, ...)
+{
+    auto pkey = cast(void *)(&keyti + 1);
+    aaA *e;
+
+    if (aa.a && aa.a.b.length)
+    {
+        auto key_hash = keyti.getHash(pkey);
+        //printf("hash = %d\n", key_hash);
+        size_t i = key_hash % aa.a.b.length;
+        auto pe = &aa.a.b[i];
+        while ((e = *pe) !is null) // null means not found
+        {
+            if (key_hash == e.hash)
+            {
+                auto c = keyti.compare(pkey, e + 1);
+                if (c == 0)
+                {
+                    if (!e.left && !e.right)
+                    {
+                        *pe = null;
+                    }
+                    else if (e.left && !e.right)
+                    {
+                        *pe = e.left;
+                         e.left = null;
+                    }
+                    else if (!e.left && e.right)
+                    {
+                        *pe = e.right;
+                         e.right = null;
+                    }
+                    else
+                    {
+                        *pe = e.left;
+                        e.left = null;
+                        do
+                            pe = &(*pe).right;
+                        while (*pe);
+                        *pe = e.right;
+                        e.right = null;
+                    }
+
+                    aa.a.nodes--;
+                    gc_free(e);
+                    break;
+                }
+                pe = (c < 0) ? &e.left : &e.right;
+            }
+            else
+                pe = (key_hash < e.hash) ? &e.left : &e.right;
+        }
+    }
+}
+
+
+/********************************************
+ * Produce array of values from aa.
+ */
+
+ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize)
+in
+{
+    assert(keysize == aligntsize(keysize));
+}
+body
+{
+    size_t resi;
+    Array a;
+
+    void _aaValues_x(aaA* e)
+    {
+        do
+        {
+            memcpy(a.ptr + resi * valuesize,
+                   cast(byte*)e + aaA.sizeof + keysize,
+                   valuesize);
+            resi++;
+            if (e.left)
+            {   if (!e.right)
+                {   e = e.left;
+                    continue;
+                }
+                _aaValues_x(e.left);
+            }
+            e = e.right;
+        } while (e !is null);
+    }
+
+    if (aa.a)
+    {
+        a.length = _aaLen(aa);
+        a.ptr = cast(byte*) gc_malloc(a.length * valuesize,
+                                      valuesize < (void*).sizeof ? BlkAttr.NO_SCAN : 0);
+        resi = 0;
+        foreach (e; aa.a.b)
+        {
+            if (e)
+                _aaValues_x(e);
+        }
+        assert(resi == a.length);
+    }
+    return *cast(ArrayRet_t*)(&a);
+}
+
+
+/********************************************
+ * Rehash an array.
+ */
+
+void* _aaRehash(AA* paa, TypeInfo keyti)
+in
+{
+    //_aaInvAh(paa);
+}
+out (result)
+{
+    //_aaInvAh(result);
+}
+body
+{
+    BB newb;
+
+    void _aaRehash_x(aaA* olde)
+    {
+        while (1)
+        {
+            auto left = olde.left;
+            auto right = olde.right;
+            olde.left = null;
+            olde.right = null;
+
+            aaA *e;
+
+            //printf("rehash %p\n", olde);
+            auto key_hash = olde.hash;
+            size_t i = key_hash % newb.b.length;
+            auto pe = &newb.b[i];
+            while ((e = *pe) !is null)
+            {
+                //printf("\te = %p, e.left = %p, e.right = %p\n", e, e.left, e.right);
+                assert(e.left != e);
+                assert(e.right != e);
+                if (key_hash == e.hash)
+                {
+                    auto c = keyti.compare(olde + 1, e + 1);
+                    assert(c != 0);
+                    pe = (c < 0) ? &e.left : &e.right;
+                }
+                else
+                    pe = (key_hash < e.hash) ? &e.left : &e.right;
+            }
+            *pe = olde;
+
+            if (right)
+            {
+                if (!left)
+                {   olde = right;
+                    continue;
+                }
+                _aaRehash_x(right);
+            }
+            if (!left)
+                break;
+            olde = left;
+        }
+    }
+
+    //printf("Rehash\n");
+    if (paa.a)
+    {
+        auto aa = paa.a;
+        auto len = _aaLen(*paa);
+        if (len)
+        {   size_t i;
+
+            for (i = 0; i < prime_list.length - 1; i++)
+            {
+                if (len <= prime_list[i])
+                    break;
+            }
+            len = prime_list[i];
+            newb.b = new aaA*[len];
+
+            foreach (e; aa.b)
+            {
+                if (e)
+                    _aaRehash_x(e);
+            }
+            delete aa.b;
+
+            newb.nodes = aa.nodes;
+            newb.keyti = aa.keyti;
+        }
+
+        *paa.a = newb;
+        _aaBalance(paa);
+    }
+    return (*paa).a;
+}
+
+/********************************************
+ * Balance an array.
+ */
+
+void _aaBalance(AA* paa)
+{
+    //printf("_aaBalance()\n");
+    if (paa.a)
+    {
+        aaA*[16] tmp;
+        aaA*[] array = tmp;
+        auto aa = paa.a;
+        foreach (j, e; aa.b)
+        {
+            /* Temporarily store contents of bucket in array[]
+             */
+            size_t k = 0;
+            void addToArray(aaA* e)
+            {
+                while (e)
+                {   addToArray(e.left);
+                    if (k == array.length)
+                        array.length = array.length * 2;
+                    array[k++] = e;
+                    e = e.right;
+                }
+            }
+            addToArray(e);
+            /* The contents of the bucket are now sorted into array[].
+             * Rebuild the tree.
+             */
+            void buildTree(aaA** p, size_t x1, size_t x2)
+            {
+                if (x1 >= x2)
+                    *p = null;
+                else
+                {   auto mid = (x1 + x2) >> 1;
+                    *p = array[mid];
+                    buildTree(&(*p).left, x1, mid);
+                    buildTree(&(*p).right, mid + 1, x2);
+                }
+            }
+            auto p = &aa.b[j];
+            buildTree(p, 0, k);
+        }
+    }
+}
+/********************************************
+ * Produce array of N byte keys from aa.
+ */
+
+ArrayRet_t _aaKeys(AA aa, size_t keysize)
+{
+    byte[] res;
+    size_t resi;
+
+    void _aaKeys_x(aaA* e)
+    {
+        do
+        {
+            memcpy(&res[resi * keysize], cast(byte*)(e + 1), keysize);
+            resi++;
+            if (e.left)
+            {   if (!e.right)
+                {   e = e.left;
+                    continue;
+                }
+                _aaKeys_x(e.left);
+            }
+            e = e.right;
+        } while (e !is null);
+    }
+
+    auto len = _aaLen(aa);
+    if (!len)
+        return 0;
+    res = (cast(byte*) gc_malloc(len * keysize,
+                                 !(aa.a.keyti.flags() & 1) ? BlkAttr.NO_SCAN : 0))[0 .. len * keysize];
+    resi = 0;
+    foreach (e; aa.a.b)
+    {
+        if (e)
+            _aaKeys_x(e);
+    }
+    assert(resi == len);
+
+    Array a;
+    a.length = len;
+    a.ptr = res.ptr;
+    return *cast(ArrayRet_t*)(&a);
+}
+
+
+/**********************************************
+ * 'apply' for associative arrays - to support foreach
+ */
+
+// dg is D, but _aaApply() is C
+extern (D) typedef int delegate(void *) dg_t;
+
+int _aaApply(AA aa, size_t keysize, dg_t dg)
+in
+{
+    assert(aligntsize(keysize) == keysize);
+}
+body
+{   int result;
+
+    //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);
+
+    int treewalker(aaA* e)
+    {   int result;
+
+        do
+        {
+            //printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
+            result = dg(cast(void *)(e + 1) + keysize);
+            if (result)
+                break;
+            if (e.right)
+            {   if (!e.left)
+                {
+                    e = e.right;
+                    continue;
+                }
+                result = treewalker(e.right);
+                if (result)
+                    break;
+            }
+            e = e.left;
+        } while (e);
+
+        return result;
+    }
+
+    if (aa.a)
+    {
+        foreach (e; aa.a.b)
+        {
+            if (e)
+            {
+                result = treewalker(e);
+                if (result)
+                    break;
+            }
+        }
+    }
+    return result;
+}
+
+// dg is D, but _aaApply2() is C
+extern (D) typedef int delegate(void *, void *) dg2_t;
+
+int _aaApply2(AA aa, size_t keysize, dg2_t dg)
+in
+{
+    assert(aligntsize(keysize) == keysize);
+}
+body
+{   int result;
+
+    //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);
+
+    int treewalker(aaA* e)
+    {   int result;
+
+        do
+        {
+            //printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
+            result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize);
+            if (result)
+                break;
+            if (e.right)
+            {   if (!e.left)
+                {
+                    e = e.right;
+                    continue;
+                }
+                result = treewalker(e.right);
+                if (result)
+                    break;
+            }
+            e = e.left;
+        } while (e);
+
+        return result;
+    }
+
+    if (aa.a)
+    {
+        foreach (e; aa.a.b)
+        {
+            if (e)
+            {
+                result = treewalker(e);
+                if (result)
+                    break;
+            }
+        }
+    }
+    return result;
+}
+
+
+/***********************************
+ * Construct an associative array of type ti from
+ * length pairs of key/value pairs.
+ */
+
+extern (C)
+BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...)
+{
+    auto valuesize = ti.next.tsize();           // value size
+    auto keyti = ti.key;
+    auto keysize = keyti.tsize();               // key size
+    BB* result;
+
+    //printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length);
+    //printf("tivalue = %.*s\n", ti.next.classinfo.name);
+    if (length == 0 || valuesize == 0 || keysize == 0)
+    {
+        ;
+    }
+    else
+    {
+        va_list q;
+        va_start!(size_t)(q, length);
+
+        result = new BB();
+        result.keyti = keyti;
+        size_t i;
+
+        for (i = 0; i < prime_list.length - 1; i++)
+        {
+            if (length <= prime_list[i])
+                break;
+        }
+        auto len = prime_list[i];
+        result.b = new aaA*[len];
+
+        size_t keystacksize   = (keysize   + int.sizeof - 1) & ~(int.sizeof - 1);
+        size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1);
+
+        size_t keytsize = aligntsize(keysize);
+
+        for (size_t j = 0; j < length; j++)
+        {   void* pkey = q;
+            q += keystacksize;
+            void* pvalue = q;
+            q += valuestacksize;
+            aaA* e;
+
+            auto key_hash = keyti.getHash(pkey);
+            //printf("hash = %d\n", key_hash);
+            i = key_hash % len;
+            auto pe = &result.b[i];
+            while (1)
+            {
+                e = *pe;
+                if (!e)
+                {
+                    // Not found, create new elem
+                    //printf("create new one\n");
+                    e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize];
+                    memcpy(e + 1, pkey, keysize);
+                    e.hash = key_hash;
+                    *pe = e;
+                    result.nodes++;
+                    break;
+                }
+                if (key_hash == e.hash)
+                {
+                    auto c = keyti.compare(pkey, e + 1);
+                    if (c == 0)
+                        break;
+                    pe = (c < 0) ? &e.left : &e.right;
+                }
+                else
+                    pe = (key_hash < e.hash) ? &e.left : &e.right;
+            }
+            memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize);
+        }
+
+        va_end(q);
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/adi.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,603 @@
+/**
+ * Implementation of dynamic array property support routines.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.adi;
+
+//debug=adi;            // uncomment to turn on debugging printf's
+
+private
+{
+    debug(adi) import core.stdc.stdio;
+    import core.stdc.string;
+    import core.stdc.stdlib;
+    import rt.util.utf;
+
+    enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001,
+        NO_SCAN  = 0b0000_0010,
+        NO_MOVE  = 0b0000_0100,
+        ALL_BITS = 0b1111_1111
+    }
+
+    extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
+    extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
+    extern (C) void  gc_free( void* p );
+}
+
+
+struct Array
+{
+    size_t  length;
+    void*   ptr;
+}
+
+/**********************************************
+ * Reverse array of chars.
+ * Handled separately because embedded multibyte encodings should not be
+ * reversed.
+ */
+
+extern (C) long _adReverseChar(char[] a)
+{
+    if (a.length > 1)
+    {
+        char[6] tmp;
+        char[6] tmplo;
+        char* lo = a.ptr;
+        char* hi = &a[length - 1];
+
+        while (lo < hi)
+        {   auto clo = *lo;
+            auto chi = *hi;
+
+            debug(adi) printf("lo = %d, hi = %d\n", lo, hi);
+            if (clo <= 0x7F && chi <= 0x7F)
+            {
+                debug(adi) printf("\tascii\n");
+                *lo = chi;
+                *hi = clo;
+                lo++;
+                hi--;
+                continue;
+            }
+
+            uint stridelo = UTF8stride[clo];
+
+            uint stridehi = 1;
+            while ((chi & 0xC0) == 0x80)
+            {
+                chi = *--hi;
+                stridehi++;
+                assert(hi >= lo);
+            }
+            if (lo == hi)
+                break;
+
+            debug(adi) printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi);
+            if (stridelo == stridehi)
+            {
+
+                memcpy(tmp.ptr, lo, stridelo);
+                memcpy(lo, hi, stridelo);
+                memcpy(hi, tmp.ptr, stridelo);
+                lo += stridelo;
+                hi--;
+                continue;
+            }
+
+            /* Shift the whole array. This is woefully inefficient
+             */
+            memcpy(tmp.ptr, hi, stridehi);
+            memcpy(tmplo.ptr, lo, stridelo);
+            memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo);
+            memcpy(lo, tmp.ptr, stridehi);
+            memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo);
+
+            lo += stridehi;
+            hi = hi - 1 + (stridehi - stridelo);
+        }
+    }
+    return *cast(long*)(&a);
+}
+
+unittest
+{
+    auto a = "abcd"c[];
+
+    auto r = a.dup.reverse;
+    //writefln(r);
+    assert(r == "dcba");
+
+    a = "a\u1235\u1234c";
+    //writefln(a);
+    r = a.dup.reverse;
+    //writefln(r);
+    assert(r == "c\u1234\u1235a");
+
+    a = "ab\u1234c";
+    //writefln(a);
+    r = a.dup.reverse;
+    //writefln(r);
+    assert(r == "c\u1234ba");
+
+    a = "\u3026\u2021\u3061\n";
+    r = a.dup.reverse;
+    assert(r == "\n\u3061\u2021\u3026");
+}
+
+
+/**********************************************
+ * Reverse array of wchars.
+ * Handled separately because embedded multiword encodings should not be
+ * reversed.
+ */
+
+extern (C) long _adReverseWchar(wchar[] a)
+{
+    if (a.length > 1)
+    {
+        wchar[2] tmp;
+        wchar* lo = a.ptr;
+        wchar* hi = &a[length - 1];
+
+        while (lo < hi)
+        {   auto clo = *lo;
+            auto chi = *hi;
+
+            if ((clo < 0xD800 || clo > 0xDFFF) &&
+                (chi < 0xD800 || chi > 0xDFFF))
+            {
+                *lo = chi;
+                *hi = clo;
+                lo++;
+                hi--;
+                continue;
+            }
+
+            int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
+
+            int stridehi = 1;
+            if (chi >= 0xDC00 && chi <= 0xDFFF)
+            {
+                chi = *--hi;
+                stridehi++;
+                assert(hi >= lo);
+            }
+            if (lo == hi)
+                break;
+
+            if (stridelo == stridehi)
+            {   int stmp;
+
+                assert(stridelo == 2);
+                assert(stmp.sizeof == 2 * (*lo).sizeof);
+                stmp = *cast(int*)lo;
+                *cast(int*)lo = *cast(int*)hi;
+                *cast(int*)hi = stmp;
+                lo += stridelo;
+                hi--;
+                continue;
+            }
+
+            /* Shift the whole array. This is woefully inefficient
+             */
+            memcpy(tmp.ptr, hi, stridehi * wchar.sizeof);
+            memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
+            memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
+            memcpy(lo, tmp.ptr, stridehi * wchar.sizeof);
+
+            lo += stridehi;
+            hi = hi - 1 + (stridehi - stridelo);
+        }
+    }
+    return *cast(long*)(&a);
+}
+
+unittest
+{
+    wstring a = "abcd";
+
+    auto r = a.dup.reverse;
+    assert(r == "dcba");
+
+    a = "a\U00012356\U00012346c";
+    r = a.dup.reverse;
+    assert(r == "c\U00012346\U00012356a");
+
+    a = "ab\U00012345c";
+    r = a.dup.reverse;
+    assert(r == "c\U00012345ba");
+}
+
+
+/**********************************************
+ * Support for array.reverse property.
+ */
+
+extern (C) long _adReverse(Array a, size_t szelem)
+out (result)
+{
+    assert(result is *cast(long*)(&a));
+}
+body
+{
+    if (a.length >= 2)
+    {
+        byte*    tmp;
+        byte[16] buffer;
+
+        void* lo = a.ptr;
+        void* hi = a.ptr + (a.length - 1) * szelem;
+
+        tmp = buffer.ptr;
+        if (szelem > 16)
+        {
+            //version (Windows)
+                tmp = cast(byte*) alloca(szelem);
+            //else
+                //tmp = gc_malloc(szelem);
+        }
+
+        for (; lo < hi; lo += szelem, hi -= szelem)
+        {
+            memcpy(tmp, lo,  szelem);
+            memcpy(lo,  hi,  szelem);
+            memcpy(hi,  tmp, szelem);
+        }
+
+        version (Windows)
+        {
+        }
+        else
+        {
+            //if (szelem > 16)
+                // BUG: bad code is generate for delete pointer, tries
+                // to call delclass.
+                //gc_free(tmp);
+        }
+    }
+    return *cast(long*)(&a);
+}
+
+unittest
+{
+    debug(adi) printf("array.reverse.unittest\n");
+
+    int[] a = new int[5];
+    int[] b;
+    size_t i;
+
+    for (i = 0; i < 5; i++)
+        a[i] = i;
+    b = a.reverse;
+    assert(b is a);
+    for (i = 0; i < 5; i++)
+        assert(a[i] == 4 - i);
+
+    struct X20
+    {   // More than 16 bytes in size
+        int a;
+        int b, c, d, e;
+    }
+
+    X20[] c = new X20[5];
+    X20[] d;
+
+    for (i = 0; i < 5; i++)
+    {   c[i].a = i;
+        c[i].e = 10;
+    }
+    d = c.reverse;
+    assert(d is c);
+    for (i = 0; i < 5; i++)
+    {
+        assert(c[i].a == 4 - i);
+        assert(c[i].e == 10);
+    }
+}
+
+/**********************************************
+ * Sort array of chars.
+ */
+
+extern (C) long _adSortChar(char[] a)
+{
+    if (a.length > 1)
+    {
+        dstring da = toUTF32(a);
+        da.sort;
+        size_t i = 0;
+        foreach (dchar d; da)
+        {   char[4] buf;
+            auto t = toUTF8(buf, d);
+            a[i .. i + t.length] = t[];
+            i += t.length;
+        }
+        delete da;
+    }
+    return *cast(long*)(&a);
+}
+
+/**********************************************
+ * Sort array of wchars.
+ */
+
+extern (C) long _adSortWchar(wchar[] a)
+{
+    if (a.length > 1)
+    {
+        dstring da = toUTF32(a);
+        da.sort;
+        size_t i = 0;
+        foreach (dchar d; da)
+        {   wchar[2] buf;
+            auto t = toUTF16(buf, d);
+            a[i .. i + t.length] = t[];
+            i += t.length;
+        }
+        delete da;
+    }
+    return *cast(long*)(&a);
+}
+
+/***************************************
+ * Support for array equality test.
+ * Returns:
+ *      1       equal
+ *      0       not equal
+ */
+
+extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
+{
+    debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
+    if (a1.length != a2.length)
+        return 0; // not equal
+    auto sz = ti.tsize();
+    auto p1 = a1.ptr;
+    auto p2 = a2.ptr;
+
+    if (sz == 1)
+        // We should really have a ti.isPOD() check for this
+        return (memcmp(p1, p2, a1.length) == 0);
+
+    for (size_t i = 0; i < a1.length; i++)
+    {
+        if (!ti.equals(p1 + i * sz, p2 + i * sz))
+            return 0; // not equal
+    }
+    return 1; // equal
+}
+
+extern (C) int _adEq2(Array a1, Array a2, TypeInfo ti)
+{
+    debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
+    if (a1.length != a2.length)
+        return 0;               // not equal
+    if (!ti.equals(&a1, &a2))
+        return 0;
+    return 1;
+}
+unittest
+{
+    debug(adi) printf("array.Eq unittest\n");
+
+    auto a = "hello"c;
+
+    assert(a != "hel");
+    assert(a != "helloo");
+    assert(a != "betty");
+    assert(a == "hello");
+    assert(a != "hxxxx");
+}
+
+/***************************************
+ * Support for array compare test.
+ */
+
+extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti)
+{
+    debug(adi) printf("adCmp()\n");
+    auto len = a1.length;
+    if (a2.length < len)
+        len = a2.length;
+    auto sz = ti.tsize();
+    void *p1 = a1.ptr;
+    void *p2 = a2.ptr;
+
+    if (sz == 1)
+    {   // We should really have a ti.isPOD() check for this
+        auto c = memcmp(p1, p2, len);
+        if (c)
+            return c;
+    }
+    else
+    {
+        for (size_t i = 0; i < len; i++)
+        {
+            auto c = ti.compare(p1 + i * sz, p2 + i * sz);
+            if (c)
+                return c;
+        }
+    }
+    if (a1.length == a2.length)
+        return 0;
+    return (a1.length > a2.length) ? 1 : -1;
+}
+
+extern (C) int _adCmp2(Array a1, Array a2, TypeInfo ti)
+{
+    debug(adi) printf("_adCmp2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
+    return ti.compare(&a1, &a2);
+}
+unittest
+{
+    debug(adi) printf("array.Cmp unittest\n");
+
+    auto a = "hello"c;
+
+    assert(a >  "hel");
+    assert(a >= "hel");
+    assert(a <  "helloo");
+    assert(a <= "helloo");
+    assert(a >  "betty");
+    assert(a >= "betty");
+    assert(a == "hello");
+    assert(a <= "hello");
+    assert(a >= "hello");
+}
+
+/***************************************
+ * Support for array compare test.
+ */
+
+extern (C) int _adCmpChar(Array a1, Array a2)
+{
+  version (X86)
+  {
+    asm
+    {   naked                   ;
+
+        push    EDI             ;
+        push    ESI             ;
+
+        mov    ESI,a1+4[4+ESP]  ;
+        mov    EDI,a2+4[4+ESP]  ;
+
+        mov    ECX,a1[4+ESP]    ;
+        mov    EDX,a2[4+ESP]    ;
+
+        cmp     ECX,EDX         ;
+        jb      GotLength       ;
+
+        mov     ECX,EDX         ;
+
+GotLength:
+        cmp    ECX,4            ;
+        jb    DoBytes           ;
+
+        // Do alignment if neither is dword aligned
+        test    ESI,3           ;
+        jz    Aligned           ;
+
+        test    EDI,3           ;
+        jz    Aligned           ;
+DoAlign:
+        mov    AL,[ESI]         ; //align ESI to dword bounds
+        mov    DL,[EDI]         ;
+
+        cmp    AL,DL            ;
+        jnz    Unequal          ;
+
+        inc    ESI              ;
+        inc    EDI              ;
+
+        test    ESI,3           ;
+
+        lea    ECX,[ECX-1]      ;
+        jnz    DoAlign          ;
+Aligned:
+        mov    EAX,ECX          ;
+
+        // do multiple of 4 bytes at a time
+
+        shr    ECX,2            ;
+        jz    TryOdd            ;
+
+        repe                    ;
+        cmpsd                   ;
+
+        jnz    UnequalQuad      ;
+
+TryOdd:
+        mov    ECX,EAX          ;
+DoBytes:
+        // if still equal and not end of string, do up to 3 bytes slightly
+        // slower.
+
+        and    ECX,3            ;
+        jz    Equal             ;
+
+        repe                    ;
+        cmpsb                   ;
+
+        jnz    Unequal          ;
+Equal:
+        mov    EAX,a1[4+ESP]    ;
+        mov    EDX,a2[4+ESP]    ;
+
+        sub    EAX,EDX          ;
+        pop    ESI              ;
+
+        pop    EDI              ;
+        ret                     ;
+
+UnequalQuad:
+        mov    EDX,[EDI-4]      ;
+        mov    EAX,[ESI-4]      ;
+
+        cmp    AL,DL            ;
+        jnz    Unequal          ;
+
+        cmp    AH,DH            ;
+        jnz    Unequal          ;
+
+        shr    EAX,16           ;
+
+        shr    EDX,16           ;
+
+        cmp    AL,DL            ;
+        jnz    Unequal          ;
+
+        cmp    AH,DH            ;
+Unequal:
+        sbb    EAX,EAX          ;
+        pop    ESI              ;
+
+        or     EAX,1            ;
+        pop    EDI              ;
+
+        ret                     ;
+    }
+  }
+  else
+  {
+    int len;
+    int c;
+
+    debug(adi) printf("adCmpChar()\n");
+    len = a1.length;
+    if (a2.length < len)
+        len = a2.length;
+    c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
+    if (!c)
+        c = cast(int)a1.length - cast(int)a2.length;
+    return c;
+  }
+}
+
+unittest
+{
+    debug(adi) printf("array.CmpChar unittest\n");
+
+    auto a = "hello"c;
+
+    assert(a >  "hel");
+    assert(a >= "hel");
+    assert(a <  "helloo");
+    assert(a <= "helloo");
+    assert(a >  "betty");
+    assert(a >= "betty");
+    assert(a == "hello");
+    assert(a <= "hello");
+    assert(a >= "hello");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/alloca.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,135 @@
+/**
+ * Implementation of alloca() standard C routine.
+ *
+ * Copyright: Copyright Digital Mars 1990 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 1990 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.alloca;
+
+/+
+#if DOS386
+extern size_t _x386_break;
+#else
+extern size_t _pastdata;
+#endif
++/
+
+/*******************************************
+ * Allocate data from the caller's stack frame.
+ * This is a 'magic' function that needs help from the compiler to
+ * work right, do not change its name, do not call it from other compilers.
+ * Input:
+ *      nbytes  number of bytes to allocate
+ *      ECX     address of variable with # of bytes in locals
+ *              This is adjusted upon return to reflect the additional
+ *              size of the stack frame.
+ * Returns:
+ *      EAX     allocated data, null if stack overflows
+ */
+
+extern (C) void* __alloca(int nbytes)
+{
+    asm
+    {
+        naked                   ;
+        mov     EDX,ECX         ;
+        mov     EAX,4[ESP]      ; // get nbytes
+        push    EBX             ;
+        push    EDI             ;
+        push    ESI             ;
+    }
+
+    version (OSX)
+    {
+    asm
+    {
+	add	EAX,15		;
+	and	EAX,0xFFFFFFF0	; // round up to 16 byte boundary
+    }
+    }
+    else
+    {
+    asm
+    {
+	add	EAX,3		;
+	and	EAX,0xFFFFFFFC	; // round up to dword
+    }
+    }
+
+    asm
+    {
+        jnz     Abegin          ;
+        mov     EAX,4           ; // allow zero bytes allocation, 0 rounded to dword is 4..
+    Abegin:
+        mov     ESI,EAX         ; // ESI = nbytes
+        neg     EAX             ;
+        add     EAX,ESP         ; // EAX is now what the new ESP will be.
+        jae     Aoverflow       ;
+    }
+    version (Windows)
+    {
+    asm
+    {
+        // We need to be careful about the guard page
+        // Thus, for every 4k page, touch it to cause the OS to load it in.
+        mov     ECX,EAX         ; // ECX is new location for stack
+        mov     EBX,ESI         ; // EBX is size to "grow" stack
+    L1:
+        test    [ECX+EBX],EBX   ; // bring in page
+        sub     EBX,0x1000      ; // next 4K page down
+        jae     L1              ; // if more pages
+        test    [ECX],EBX       ; // bring in last page
+    }
+    }
+    version (DOS386)
+    {
+    asm
+    {
+        // is ESP off bottom?
+        cmp     EAX,_x386_break ;
+        jbe     Aoverflow       ;
+    }
+    }
+    version (Unix)
+    {
+    asm
+    {
+        cmp     EAX,_pastdata   ;
+        jbe     Aoverflow       ; // Unlikely - ~2 Gbytes under UNIX
+    }
+    }
+    asm
+    {
+        // Copy down to [ESP] the temps on the stack.
+        // The number of temps is (EBP - ESP - locals).
+        mov     ECX,EBP         ;
+        sub     ECX,ESP         ;
+        sub     ECX,[EDX]       ; // ECX = number of temps (bytes) to move.
+        add     [EDX],ESI       ; // adjust locals by nbytes for next call to alloca()
+        mov     ESP,EAX         ; // Set up new stack pointer.
+        add     EAX,ECX         ; // Return value = ESP + temps.
+        mov     EDI,ESP         ; // Destination of copy of temps.
+        add     ESI,ESP         ; // Source of copy.
+        shr     ECX,2           ; // ECX to count of dwords in temps
+                                  // Always at least 4 (nbytes, EIP, ESI,and EDI).
+        rep                     ;
+        movsd                   ;
+        jmp     done            ;
+
+    Aoverflow:
+        // Overflowed the stack.  Return null
+        xor     EAX,EAX         ;
+
+    done:
+        pop     ESI             ;
+        pop     EDI             ;
+        pop     EBX             ;
+        ret                     ;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/arrayassign.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,186 @@
+/**
+ * Implementation of array assignment support routines.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arrayassign;
+
+private
+{
+    import rt.util.string;
+    import core.stdc.string;
+    import core.stdc.stdlib;
+    debug(PRINTF) import core.stdc.stdio;
+}
+
+/**
+ * Does array assignment (not construction) from another
+ * array of the same element type.
+ * ti is the element type.
+ * Handles overlapping copies.
+ */
+extern (C) void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to)
+{
+    debug(PRINTF) printf("_d_arrayassign(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize());
+
+    if (to.length != from.length)
+    {
+        char[10] tmp = void;
+        string msg = "lengths don't match for array copy,"c;
+        msg ~= tmp.intToString(to.length) ~ " = " ~ tmp.intToString(from.length);
+        throw new Exception(msg);
+    }
+
+    auto element_size = ti.tsize();
+
+    /* Need a temporary buffer tmp[] big enough to hold one element
+     */
+    void[16] buf = void;
+    void[] tmp;
+    if (element_size > buf.sizeof)
+        tmp = alloca(element_size)[0 .. element_size];
+    else
+        tmp = buf;
+
+
+    if (to.ptr <= from.ptr)
+    {
+        foreach (i; 0 .. to.length)
+        {
+            void* pto   = to.ptr   + i * element_size;
+            void* pfrom = from.ptr + i * element_size;
+            memcpy(tmp.ptr, pto, element_size);
+            memcpy(pto, pfrom, element_size);
+            ti.postblit(pto);
+            ti.destroy(tmp.ptr);
+        }
+    }
+    else
+    {
+        for (int i = to.length; i--; )
+        {
+            void* pto   = to.ptr   + i * element_size;
+            void* pfrom = from.ptr + i * element_size;
+            memcpy(tmp.ptr, pto, element_size);
+            memcpy(pto, pfrom, element_size);
+            ti.postblit(pto);
+            ti.destroy(tmp.ptr);
+        }
+    }
+    return to;
+}
+
+/**
+ * Does array initialization (not assignment) from another
+ * array of the same element type.
+ * ti is the element type.
+ */
+extern (C) void[] _d_arrayctor(TypeInfo ti, void[] from, void[] to)
+{
+    debug(PRINTF) printf("_d_arrayctor(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize());
+
+    if (to.length != from.length)
+    {
+        char[10] tmp = void;
+        string msg = "lengths don't match for array initialization,"c;
+        msg ~= tmp.intToString(to.length) ~ " = " ~ tmp.intToString(from.length);
+        throw new Exception(msg);
+    }
+
+    auto element_size = ti.tsize();
+
+    int i;
+    try
+    {
+        for (i = 0; i < to.length; i++)
+        {
+            // Copy construction is defined as bit copy followed by postblit.
+            memcpy(to.ptr + i * element_size, from.ptr + i * element_size, element_size);
+            ti.postblit(to.ptr + i * element_size);
+        }
+    }
+    catch (Object o)
+    {
+        /* Destroy, in reverse order, what we've constructed so far
+         */
+        while (i--)
+        {
+            ti.destroy(to.ptr + i * element_size);
+        }
+
+        throw o;
+    }
+    return to;
+}
+
+
+/**
+ * Do assignment to an array.
+ *      p[0 .. count] = value;
+ */
+extern (C) void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti)
+{
+    void* pstart = p;
+
+    auto element_size = ti.tsize();
+
+    //Need a temporary buffer tmp[] big enough to hold one element
+    void[16] buf = void;
+    void[] tmp;
+    if (element_size > buf.sizeof)
+    {
+        tmp = alloca(element_size)[0 .. element_size];
+    }
+    else
+        tmp = buf;
+
+    foreach (i; 0 .. count)
+    {
+        memcpy(tmp.ptr, p, element_size);
+        memcpy(p, value, element_size);
+        ti.postblit(p);
+        ti.destroy(tmp.ptr);
+        p += element_size;
+    }
+    return pstart;
+}
+
+/**
+ * Do construction of an array.
+ *      ti[count] p = value;
+ */
+extern (C) void* _d_arraysetctor(void* p, void* value, int count, TypeInfo ti)
+{
+    void* pstart = p;
+    auto element_size = ti.tsize();
+
+    try
+    {
+        foreach (i; 0 .. count)
+        {
+            // Copy construction is defined as bit copy followed by postblit.
+            memcpy(p, value, element_size);
+            ti.postblit(p);
+            p += element_size;
+        }
+    }
+    catch (Object o)
+    {
+        // Destroy, in reverse order, what we've constructed so far
+        while (p > pstart)
+        {
+            p -= element_size;
+            ti.destroy(p);
+        }
+
+        throw o;
+    }
+    return pstart;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/arraybyte.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,1893 @@
+/**
+ * Contains SSE2 and MMX versions of certain operations for char, byte, and
+ * ubyte ('a', 'g' and 'h' suffixes).
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arraybyte;
+
+import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 4;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.amd3dnow amd3dnow;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+alias byte T;
+
+extern (C):
+
+/* ======================================================================== */
+
+
+/***********************
+ * Computes:
+ *      a[] = b[] + value
+ */
+
+T[] _arraySliceExpAddSliceAssign_a(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_g(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_h(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_g(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_g(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpAddSliceAssign_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1088% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startaddsse2u:
+                    add ESI, 64;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM2, [EAX+32];
+                    movdqu XMM3, [EAX+48];
+                    add EAX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM4;
+                    paddb XMM2, XMM4;
+                    paddb XMM3, XMM4;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startaddsse2a:
+                    add ESI, 64;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM2, [EAX+32];
+                    movdqa XMM3, [EAX+48];
+                    add EAX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM4;
+                    paddb XMM2, XMM4;
+                    paddb XMM3, XMM4;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 1000% faster
+        if (mmx() && a.length >= 32)
+        {
+            auto n = aptr + (a.length & ~31);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 4;
+            startaddmmx:
+                add ESI, 32;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                add EAX, 32;
+                paddb MM0, MM4;
+                paddb MM1, MM4;
+                paddb MM2, MM4;
+                paddb MM3, MM4;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startaddmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        /* trying to be fair and treat normal 32-bit cpu the same way as we do
+         * the SIMD units, with unrolled asm.  There's not enough registers,
+         * really.
+         */
+        else
+        if (a.length >= 4)
+        {
+
+            auto n = aptr + (a.length & ~3);
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov CL, value;
+
+                align 4;
+            startadd386:
+                add ESI, 4;
+                mov DX, [EAX];
+                mov BX, [EAX+2];
+                add EAX, 4;
+                add BL, CL;
+                add BH, CL;
+                add DL, CL;
+                add DH, CL;
+                mov [ESI   -4], DX;
+                mov [ESI+2 -4], BX;
+                cmp ESI, EDI;
+                jb startadd386;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ + value);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpAddSliceAssign_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_a(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_g(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_h(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_g(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_g(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceAddSliceAssign_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 5739% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                version (log) printf("\tsse2 unaligned\n");
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 8;
+                startaddlsse2u:
+                    add ESI, 64;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM2, [EAX+32];
+                    movdqu XMM3, [EAX+48];
+                    add EAX, 64;
+                    movdqu XMM4, [ECX];
+                    movdqu XMM5, [ECX+16];
+                    movdqu XMM6, [ECX+32];
+                    movdqu XMM7, [ECX+48];
+                    add ECX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM5;
+                    paddb XMM2, XMM6;
+                    paddb XMM3, XMM7;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddlsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                version (log) printf("\tsse2 aligned\n");
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 8;
+                startaddlsse2a:
+                    add ESI, 64;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM2, [EAX+32];
+                    movdqa XMM3, [EAX+48];
+                    add EAX, 64;
+                    movdqa XMM4, [ECX];
+                    movdqa XMM5, [ECX+16];
+                    movdqa XMM6, [ECX+32];
+                    movdqa XMM7, [ECX+48];
+                    add ECX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM5;
+                    paddb XMM2, XMM6;
+                    paddb XMM3, XMM7;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddlsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 4428% faster
+        if (mmx() && a.length >= 32)
+        {
+            version (log) printf("\tmmx\n");
+            auto n = aptr + (a.length & ~31);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startaddlmmx:
+                add ESI, 32;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                add EAX, 32;
+                movq MM4, [ECX];
+                movq MM5, [ECX+8];
+                movq MM6, [ECX+16];
+                movq MM7, [ECX+24];
+                add ECX, 32;
+                paddb MM0, MM4;
+                paddb MM1, MM5;
+                paddb MM2, MM6;
+                paddb MM3, MM7;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startaddlmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    version (log) if (aptr < aend) printf("\tbase\n");
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ + *cptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += value
+ */
+
+T[] _arrayExpSliceAddass_a(T[] a, T value)
+{
+    return _arrayExpSliceAddass_g(a, value);
+}
+
+T[] _arrayExpSliceAddass_h(T[] a, T value)
+{
+    return _arrayExpSliceAddass_g(a, value);
+}
+
+T[] _arrayExpSliceAddass_g(T[] a, T value)
+{
+    //printf("_arrayExpSliceAddass_g(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1578% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+            l |= (l << 16);
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startaddasssse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM2, [ESI+32];
+                    movdqu XMM3, [ESI+48];
+                    add ESI, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM4;
+                    paddb XMM2, XMM4;
+                    paddb XMM3, XMM4;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddasssse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startaddasssse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM2, [ESI+32];
+                    movdqa XMM3, [ESI+48];
+                    add ESI, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM4;
+                    paddb XMM2, XMM4;
+                    paddb XMM3, XMM4;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddasssse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 1721% faster
+        if (mmx() && a.length >= 32)
+        {
+
+            auto n = aptr + (a.length & ~31);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 8;
+            startaddassmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                add ESI, 32;
+                paddb MM0, MM4;
+                paddb MM1, MM4;
+                paddb MM2, MM4;
+                paddb MM3, MM4;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startaddassmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceAddass_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += b[]
+ */
+
+T[] _arraySliceSliceAddass_a(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_g(a, b);
+}
+
+T[] _arraySliceSliceAddass_h(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_g(a, b);
+}
+
+T[] _arraySliceSliceAddass_g(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceAddass_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 4727% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 8;
+                startaddasslsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM2, [ESI+32];
+                    movdqu XMM3, [ESI+48];
+                    add ESI, 64;
+                    movdqu XMM4, [ECX];
+                    movdqu XMM5, [ECX+16];
+                    movdqu XMM6, [ECX+32];
+                    movdqu XMM7, [ECX+48];
+                    add ECX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM5;
+                    paddb XMM2, XMM6;
+                    paddb XMM3, XMM7;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddasslsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 8;
+                startaddasslsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM2, [ESI+32];
+                    movdqa XMM3, [ESI+48];
+                    add ESI, 64;
+                    movdqa XMM4, [ECX];
+                    movdqa XMM5, [ECX+16];
+                    movdqa XMM6, [ECX+32];
+                    movdqa XMM7, [ECX+48];
+                    add ECX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM5;
+                    paddb XMM2, XMM6;
+                    paddb XMM3, XMM7;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddasslsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 3059% faster
+        if (mmx() && a.length >= 32)
+        {
+
+            auto n = aptr + (a.length & ~31);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 8;
+            startaddasslmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                add ESI, 32;
+                movq MM4, [ECX];
+                movq MM5, [ECX+8];
+                movq MM6, [ECX+16];
+                movq MM7, [ECX+24];
+                add ECX, 32;
+                paddb MM0, MM4;
+                paddb MM1, MM5;
+                paddb MM2, MM6;
+                paddb MM3, MM7;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startaddasslmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddass_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+
+/***********************
+ * Computes:
+ *      a[] = b[] - value
+ */
+
+T[] _arraySliceExpMinSliceAssign_a(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_g(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_h(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_g(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_g(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMinSliceAssign_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1189% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubsse2u:
+                    add ESI, 64;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM2, [EAX+32];
+                    movdqu XMM3, [EAX+48];
+                    add EAX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM4;
+                    psubb XMM2, XMM4;
+                    psubb XMM3, XMM4;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubsse2a:
+                    add ESI, 64;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM2, [EAX+32];
+                    movdqa XMM3, [EAX+48];
+                    add EAX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM4;
+                    psubb XMM2, XMM4;
+                    psubb XMM3, XMM4;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 1079% faster
+        if (mmx() && a.length >= 32)
+        {
+            auto n = aptr + (a.length & ~31);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 4;
+            startsubmmx:
+                add ESI, 32;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                add EAX, 32;
+                psubb MM0, MM4;
+                psubb MM1, MM4;
+                psubb MM2, MM4;
+                psubb MM3, MM4;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startsubmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        // trying to be fair and treat normal 32-bit cpu the same way as we do the SIMD units, with unrolled asm.  There's not enough registers, really.
+        else
+        if (a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov CL, value;
+
+                align 4;
+            startsub386:
+                add ESI, 4;
+                mov DX, [EAX];
+                mov BX, [EAX+2];
+                add EAX, 4;
+                sub BL, CL;
+                sub BH, CL;
+                sub DL, CL;
+                sub DH, CL;
+                mov [ESI   -4], DX;
+                mov [ESI+2 -4], BX;
+                cmp ESI, EDI;
+                jb startsub386;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ - value);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMinSliceAssign_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] = b[] - 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(b[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, c[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = value - b[]
+ */
+
+T[] _arrayExpSliceMinSliceAssign_a(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_g(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_h(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_g(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_g(T[] a, T[] b, T value)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arrayExpSliceMinSliceAssign_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 8748% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubrsse2u:
+                    add ESI, 64;
+                    movdqa XMM5, XMM4;
+                    movdqa XMM6, XMM4;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    psubb XMM5, XMM0;
+                    psubb XMM6, XMM1;
+                    movdqu [ESI   -64], XMM5;
+                    movdqu [ESI+16-64], XMM6;
+                    movdqa XMM5, XMM4;
+                    movdqa XMM6, XMM4;
+                    movdqu XMM2, [EAX+32];
+                    movdqu XMM3, [EAX+48];
+                    add EAX, 64;
+                    psubb XMM5, XMM2;
+                    psubb XMM6, XMM3;
+                    movdqu [ESI+32-64], XMM5;
+                    movdqu [ESI+48-64], XMM6;
+                    cmp ESI, EDI;
+                    jb startsubrsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubrsse2a:
+                    add ESI, 64;
+                    movdqa XMM5, XMM4;
+                    movdqa XMM6, XMM4;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    psubb XMM5, XMM0;
+                    psubb XMM6, XMM1;
+                    movdqa [ESI   -64], XMM5;
+                    movdqa [ESI+16-64], XMM6;
+                    movdqa XMM5, XMM4;
+                    movdqa XMM6, XMM4;
+                    movdqa XMM2, [EAX+32];
+                    movdqa XMM3, [EAX+48];
+                    add EAX, 64;
+                    psubb XMM5, XMM2;
+                    psubb XMM6, XMM3;
+                    movdqa [ESI+32-64], XMM5;
+                    movdqa [ESI+48-64], XMM6;
+                    cmp ESI, EDI;
+                    jb startsubrsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 7397% faster
+        if (mmx() && a.length >= 32)
+        {
+            auto n = aptr + (a.length & ~31);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 4;
+            startsubrmmx:
+                add ESI, 32;
+                movq MM5, MM4;
+                movq MM6, MM4;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                psubb MM5, MM0;
+                psubb MM6, MM1;
+                movq [ESI   -32], MM5;
+                movq [ESI+8 -32], MM6;
+                movq MM5, MM4;
+                movq MM6, MM4;
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                add EAX, 32;
+                psubb MM5, MM2;
+                psubb MM6, MM3;
+                movq [ESI+16-32], MM5;
+                movq [ESI+24-32], MM6;
+                cmp ESI, EDI;
+                jb startsubrmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(value - *bptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinSliceAssign_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] = 6 - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(6 - b[i]))
+                {
+                    printf("[%d]: %d != 6 - %d\n", i, c[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_a(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_g(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_h(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_g(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_g(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 5756% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 8;
+                startsublsse2u:
+                    add ESI, 64;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM2, [EAX+32];
+                    movdqu XMM3, [EAX+48];
+                    add EAX, 64;
+                    movdqu XMM4, [ECX];
+                    movdqu XMM5, [ECX+16];
+                    movdqu XMM6, [ECX+32];
+                    movdqu XMM7, [ECX+48];
+                    add ECX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM5;
+                    psubb XMM2, XMM6;
+                    psubb XMM3, XMM7;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsublsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 8;
+                startsublsse2a:
+                    add ESI, 64;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM2, [EAX+32];
+                    movdqa XMM3, [EAX+48];
+                    add EAX, 64;
+                    movdqa XMM4, [ECX];
+                    movdqa XMM5, [ECX+16];
+                    movdqa XMM6, [ECX+32];
+                    movdqa XMM7, [ECX+48];
+                    add ECX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM5;
+                    psubb XMM2, XMM6;
+                    psubb XMM3, XMM7;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsublsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 4428% faster
+        if (mmx() && a.length >= 32)
+        {
+            auto n = aptr + (a.length & ~31);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 8;
+            startsublmmx:
+                add ESI, 32;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                add EAX, 32;
+                movq MM4, [ECX];
+                movq MM5, [ECX+8];
+                movq MM6, [ECX+16];
+                movq MM7, [ECX+24];
+                add ECX, 32;
+                psubb MM0, MM4;
+                psubb MM1, MM5;
+                psubb MM2, MM6;
+                psubb MM3, MM7;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startsublmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ - *cptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= value
+ */
+
+T[] _arrayExpSliceMinass_a(T[] a, T value)
+{
+    return _arrayExpSliceMinass_g(a, value);
+}
+
+T[] _arrayExpSliceMinass_h(T[] a, T value)
+{
+    return _arrayExpSliceMinass_g(a, value);
+}
+
+T[] _arrayExpSliceMinass_g(T[] a, T value)
+{
+    //printf("_arrayExpSliceMinass_g(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1577% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+            l |= (l << 16);
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubasssse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM2, [ESI+32];
+                    movdqu XMM3, [ESI+48];
+                    add ESI, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM4;
+                    psubb XMM2, XMM4;
+                    psubb XMM3, XMM4;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubasssse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubasssse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM2, [ESI+32];
+                    movdqa XMM3, [ESI+48];
+                    add ESI, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM4;
+                    psubb XMM2, XMM4;
+                    psubb XMM3, XMM4;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubasssse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 1577% faster
+        if (mmx() && a.length >= 32)
+        {
+
+            auto n = aptr + (a.length & ~31);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 8;
+            startsubassmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                add ESI, 32;
+                psubb MM0, MM4;
+                psubb MM1, MM4;
+                psubb MM2, MM4;
+                psubb MM3, MM4;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startsubassmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[]
+ */
+
+T[] _arraySliceSliceMinass_a(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_g(a, b);
+}
+
+T[] _arraySliceSliceMinass_h(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_g(a, b);
+}
+
+T[] _arraySliceSliceMinass_g(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMinass_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 4800% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 8;
+                startsubasslsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM2, [ESI+32];
+                    movdqu XMM3, [ESI+48];
+                    add ESI, 64;
+                    movdqu XMM4, [ECX];
+                    movdqu XMM5, [ECX+16];
+                    movdqu XMM6, [ECX+32];
+                    movdqu XMM7, [ECX+48];
+                    add ECX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM5;
+                    psubb XMM2, XMM6;
+                    psubb XMM3, XMM7;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubasslsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 8;
+                startsubasslsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM2, [ESI+32];
+                    movdqa XMM3, [ESI+48];
+                    add ESI, 64;
+                    movdqa XMM4, [ECX];
+                    movdqa XMM5, [ECX+16];
+                    movdqa XMM6, [ECX+32];
+                    movdqa XMM7, [ECX+48];
+                    add ECX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM5;
+                    psubb XMM2, XMM6;
+                    psubb XMM3, XMM7;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubasslsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 3107% faster
+        if (mmx() && a.length >= 32)
+        {
+
+            auto n = aptr + (a.length & ~31);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 8;
+            startsubasslmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                add ESI, 32;
+                movq MM4, [ECX];
+                movq MM5, [ECX+8];
+                movq MM6, [ECX+16];
+                movq MM7, [ECX+24];
+                add ECX, 32;
+                psubb MM0, MM4;
+                psubb MM1, MM5;
+                psubb MM2, MM6;
+                psubb MM3, MM7;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startsubasslmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinass_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/arraycast.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,94 @@
+/**
+ * Implementation of array cast support routines.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arraycast;
+
+/******************************************
+ * Runtime helper to convert dynamic array of one
+ * type to dynamic array of another.
+ * Adjusts the length of the array.
+ * Throws exception if new length is not aligned.
+ */
+
+extern (C)
+
+void[] _d_arraycast(size_t tsize, size_t fsize, void[] a)
+{
+    auto length = a.length;
+
+    auto nbytes = length * fsize;
+    if (nbytes % tsize != 0)
+    {
+    throw new Exception("array cast misalignment");
+    }
+    length = nbytes / tsize;
+    *cast(size_t *)&a = length; // jam new length
+    return a;
+}
+
+unittest
+{
+    byte[int.sizeof * 3] b;
+    int[] i;
+    short[] s;
+
+    i = cast(int[])b;
+    assert(i.length == 3);
+
+    s = cast(short[])b;
+    assert(s.length == 6);
+
+    s = cast(short[])i;
+    assert(s.length == 6);
+}
+
+/******************************************
+ * Runtime helper to convert dynamic array of bits
+ * dynamic array of another.
+ * Adjusts the length of the array.
+ * Throws exception if new length is not aligned.
+ */
+
+version (none)
+{
+extern (C)
+
+void[] _d_arraycast_frombit(uint tsize, void[] a)
+{
+    uint length = a.length;
+
+    if (length & 7)
+    {
+    throw new Exception("bit[] array cast misalignment");
+    }
+    length /= 8 * tsize;
+    *cast(size_t *)&a = length; // jam new length
+    return a;
+}
+
+unittest
+{
+    version (D_Bits)
+    {
+    bit[int.sizeof * 3 * 8] b;
+    int[] i;
+    short[] s;
+
+    i = cast(int[])b;
+    assert(i.length == 3);
+
+    s = cast(short[])b;
+    assert(s.length == 6);
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/arraycat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,42 @@
+/**
+ * Implementation of array copy support routines.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arraycat;
+
+private
+{
+    import core.stdc.string;
+    debug import core.stdc.stdio;
+}
+
+extern (C):
+
+byte[] _d_arraycopy(size_t size, byte[] from, byte[] to)
+{
+    debug printf("f = %p,%d, t = %p,%d, size = %d\n",
+                 from.ptr, from.length, to.ptr, to.length, size);
+
+    if (to.length != from.length)
+    {
+        throw new Exception("lengths don't match for array copy");
+    }
+    else if (to.ptr + to.length * size <= from.ptr ||
+             from.ptr + from.length * size <= to.ptr)
+    {
+        memcpy(to.ptr, from.ptr, to.length * size);
+    }
+    else
+    {
+        throw new Exception("overlapping array copy");
+    }
+    return to;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/arraydouble.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,1720 @@
+/**
+ * Contains SSE2 and MMX versions of certain operations for double.
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arraydouble;
+
+private import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 5;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.amd3dnow amd3dnow;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+/* Performance figures measured by Burton Radons
+ */
+
+alias double T;
+
+extern (C):
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_d(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 333% faster
+        if (sse2() && b.length >= 16)
+        {
+            auto n = aptr + (b.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add ESI, 64;
+                addpd XMM0, XMM4;
+                addpd XMM1, XMM5;
+                addpd XMM2, XMM6;
+                addpd XMM3, XMM7;
+                add ECX, 64;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ = *bptr++ + *cptr++;
+
+    return a;
+}
+
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_d(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 324% faster
+        if (sse2() && b.length >= 8)
+        {
+            auto n = aptr + (b.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add ESI, 64;
+                subpd XMM0, XMM4;
+                subpd XMM1, XMM5;
+                subpd XMM2, XMM6;
+                subpd XMM3, XMM7;
+                add ECX, 64;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ = *bptr++ - *cptr++;
+
+    return a;
+}
+
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %g != %g - %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + value
+ */
+
+T[] _arraySliceExpAddSliceAssign_d(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpAddSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 305% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                addpd XMM0, XMM4;
+                addpd XMM1, XMM4;
+                addpd XMM2, XMM4;
+                addpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ + value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpAddSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %g != %g + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += value
+ */
+
+T[] _arrayExpSliceAddass_d(T[] a, T value)
+{
+    //printf("_arrayExpSliceAddass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 114% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = cast(T*)((cast(uint)aend) & ~7);
+            if (aptr < n)
+
+            // Unaligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                addpd XMM0, XMM4;
+                addpd XMM1, XMM4;
+                addpd XMM2, XMM4;
+                addpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceAddass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %g != %g + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += b[]
+ */
+
+T[] _arraySliceSliceAddass_d(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceAddass_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 183% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add ECX, 64;
+                addpd XMM0, XMM4;
+                addpd XMM1, XMM5;
+                addpd XMM2, XMM6;
+                addpd XMM3, XMM7;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - value
+ */
+
+T[] _arraySliceExpMinSliceAssign_d(T[] a, T value, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMinSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 305% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                subpd XMM0, XMM4;
+                subpd XMM1, XMM4;
+                subpd XMM2, XMM4;
+                subpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ - value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMinSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = value - b[]
+ */
+
+T[] _arrayExpSliceMinSliceAssign_d(T[] a, T[] b, T value)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arrayExpSliceMinSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 66% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movapd XMM5, XMM4;
+                movapd XMM6, XMM4;
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                subpd XMM5, XMM0;
+                subpd XMM6, XMM1;
+                movupd [ESI+ 0-64], XMM5;
+                movupd [ESI+16-64], XMM6;
+                movapd XMM5, XMM4;
+                movapd XMM6, XMM4;
+                subpd XMM5, XMM2;
+                subpd XMM6, XMM3;
+                movupd [ESI+32-64], XMM5;
+                movupd [ESI+48-64], XMM6;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = value - *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = 6 - a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(6 - a[i]))
+                {
+                    printf("[%d]: %g != 6 - %g\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= value
+ */
+
+T[] _arrayExpSliceMinass_d(T[] a, T value)
+{
+    //printf("_arrayExpSliceMinass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 115% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = cast(T*)((cast(uint)aend) & ~7);
+            if (aptr < n)
+
+            // Unaligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                subpd XMM0, XMM4;
+                subpd XMM1, XMM4;
+                subpd XMM2, XMM4;
+                subpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[]
+ */
+
+T[] _arraySliceSliceMinass_d(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMinass_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 183% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add ECX, 64;
+                subpd XMM0, XMM4;
+                subpd XMM1, XMM5;
+                subpd XMM2, XMM6;
+                subpd XMM3, XMM7;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAssign_d(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMulSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 304% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM4;
+                mulpd XMM2, XMM4;
+                mulpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * c[]
+ */
+
+T[] _arraySliceSliceMulSliceAssign_d(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceMulSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 329% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add ESI, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add EAX, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM5;
+                mulpd XMM2, XMM6;
+                mulpd XMM3, XMM7;
+                add ECX, 64;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * *cptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * b[i]))
+                {
+                    printf("[%d]: %g != %g * %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= value
+ */
+
+T[] _arrayExpSliceMulass_d(T[] a, T value)
+{
+    //printf("_arrayExpSliceMulass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 109% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = cast(T*)((cast(uint)aend) & ~7);
+            if (aptr < n)
+
+            // Unaligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM4;
+                mulpd XMM2, XMM4;
+                mulpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= b[]
+ */
+
+T[] _arraySliceSliceMulass_d(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMulass_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 205% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add ECX, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM5;
+                mulpd XMM2, XMM6;
+                mulpd XMM3, XMM7;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] / value
+ */
+
+T[] _arraySliceExpDivSliceAssign_d(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpDivSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    /* Multiplying by the reciprocal is faster, but does
+     * not produce as accurate an answer.
+     */
+    T recip = cast(T)1 / value;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 299% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, recip;
+                //movsd XMM4, value
+                //rcpsd XMM4, XMM4
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM4;
+                mulpd XMM2, XMM4;
+                mulpd XMM3, XMM4;
+                //divpd XMM0, XMM4;
+                //divpd XMM1, XMM4;
+                //divpd XMM2, XMM4;
+                //divpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+    {
+        *aptr++ = *bptr++ / value;
+        //*aptr++ = *bptr++ * recip;
+    }
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpDivSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] / 8;
+
+            for (int i = 0; i < dim; i++)
+            {
+                //printf("[%d]: %g ?= %g / 8\n", i, c[i], a[i]);
+                if (c[i] != cast(T)(a[i] / 8))
+                {
+                    printf("[%d]: %g != %g / 8\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] /= value
+ */
+
+T[] _arrayExpSliceDivass_d(T[] a, T value)
+{
+    //printf("_arrayExpSliceDivass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    /* Multiplying by the reciprocal is faster, but does
+     * not produce as accurate an answer.
+     */
+    T recip = cast(T)1 / value;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 65% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, recip;
+                //movsd XMM4, value
+                //rcpsd XMM4, XMM4
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM4;
+                mulpd XMM2, XMM4;
+                mulpd XMM3, XMM4;
+                //divpd XMM0, XMM4;
+                //divpd XMM1, XMM4;
+                //divpd XMM2, XMM4;
+                //divpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= recip;
+
+    return a;
+}
+
+
+unittest
+{
+    printf("_arrayExpSliceDivass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] /= 8;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] / 8))
+                {
+                    printf("[%d]: %g != %g / 8\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[] * value
+ */
+
+T[] _arraySliceExpMulSliceMinass_d(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAddass_d(a, -value, b);
+}
+
+/***********************
+ * Computes:
+ *      a[] += b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAddass_d(T[] a, T value, T[] b)
+in
+{
+        assert(a.length == b.length);
+        assert(disjoint(a, b));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ += *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAddass_d unittest\n");
+
+    cpuid = 1;
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 1; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] += a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                //printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]);
+                if (c[i] != cast(T)(b[i] + a[i] * 6))
+                {
+                    printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/arrayfloat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,2309 @@
+/**
+ * Contains SSE2 and MMX versions of certain operations for float.
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arrayfloat;
+
+private import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 5;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.amd3dnow amd3dnow;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+alias float T;
+
+extern (C):
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_f(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceAddSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 834% faster
+        if (sse() && b.length >= 16)
+        {
+            version (log) printf("\tsse unaligned\n");
+            auto n = aptr + (b.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add ESI, 64;
+                addps XMM0, XMM4;
+                addps XMM1, XMM5;
+                addps XMM2, XMM6;
+                addps XMM3, XMM7;
+                add ECX, 64;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is only 13% faster
+        if (amd3dnow() && b.length >= 8)
+        {
+            version (log) printf("\tamd3dnow\n");
+            auto n = aptr + (b.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+
+                align 4;
+            start3dnow:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfadd MM0, [ECX];
+                pfadd MM1, [ECX+8];
+                pfadd MM2, [ECX+16];
+                pfadd MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ECX, 32;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    // Handle remainder
+    version (log) if (aptr < aend) printf("\tbase\n");
+    while (aptr < aend)
+        *aptr++ = *bptr++ + *cptr++;
+
+    return a;
+}
+
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_f(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 834% faster
+        if (sse() && b.length >= 16)
+        {
+            auto n = aptr + (b.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add ESI, 64;
+                subps XMM0, XMM4;
+                subps XMM1, XMM5;
+                subps XMM2, XMM6;
+                subps XMM3, XMM7;
+                add ECX, 64;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is only 13% faster
+        if (amd3dnow() && b.length >= 8)
+        {
+            auto n = aptr + (b.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+
+                align 4;
+            start3dnow:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfsub MM0, [ECX];
+                pfsub MM1, [ECX+8];
+                pfsub MM2, [ECX+16];
+                pfsub MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ECX, 32;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ = *bptr++ - *cptr++;
+
+    return a;
+}
+
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %g != %gd - %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + value
+ */
+
+T[] _arraySliceExpAddSliceAssign_f(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpAddSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 665% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                addps XMM0, XMM4;
+                addps XMM1, XMM4;
+                addps XMM2, XMM4;
+                addps XMM3, XMM4;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        // 3DNow! version is 69% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start3dnow:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfadd MM0, MM4;
+                pfadd MM1, MM4;
+                pfadd MM2, MM4;
+                pfadd MM3, MM4;
+                movq [ESI],    MM0;
+                movq [ESI+8],  MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ + value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpAddSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %g != %g + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += value
+ */
+
+T[] _arrayExpSliceAddass_f(T[] a, T value)
+{
+    //printf("_arrayExpSliceAddass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 302% faster
+        if (sse() && a.length >= 16)
+        {
+            // align pointer
+            auto n = cast(T*)((cast(uint)aptr + 15) & ~15);
+            while (aptr < n)
+                *aptr++ += value;
+            n = cast(T*)((cast(uint)aend) & ~15);
+            if (aptr < n)
+
+            // Aligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movaps XMM0, [ESI];
+                movaps XMM1, [ESI+16];
+                movaps XMM2, [ESI+32];
+                movaps XMM3, [ESI+48];
+                add ESI, 64;
+                addps XMM0, XMM4;
+                addps XMM1, XMM4;
+                addps XMM2, XMM4;
+                addps XMM3, XMM4;
+                movaps [ESI+ 0-64], XMM0;
+                movaps [ESI+16-64], XMM1;
+                movaps [ESI+32-64], XMM2;
+                movaps [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+        else
+        // 3DNow! version is 63% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start3dnow:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfadd MM0, MM4;
+                pfadd MM1, MM4;
+                pfadd MM2, MM4;
+                pfadd MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceAddass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %g != %g + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += b[]
+ */
+
+T[] _arraySliceSliceAddass_f(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceAddass_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 468% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [ESI];
+                movups XMM1, [ESI+16];
+                movups XMM2, [ESI+32];
+                movups XMM3, [ESI+48];
+                add ESI, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add ECX, 64;
+                addps XMM0, XMM4;
+                addps XMM1, XMM5;
+                addps XMM2, XMM6;
+                addps XMM3, XMM7;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is 57% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr]; // destination operand
+                mov EDI, dword ptr [n];    // end comparison
+                mov ECX, dword ptr [bptr]; // right operand
+
+                align 4;
+            start3dnow:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfadd MM0, [ECX];
+                pfadd MM1, [ECX+8];
+                pfadd MM2, [ECX+16];
+                pfadd MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add ECX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+                mov dword ptr [bptr], ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - value
+ */
+
+T[] _arraySliceExpMinSliceAssign_f(T[] a, T value, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMinSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 622% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                subps XMM0, XMM4;
+                subps XMM1, XMM4;
+                subps XMM2, XMM4;
+                subps XMM3, XMM4;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        // 3DNow! version is 67% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            T[2] w;
+
+            w[0] = w[1] = value;
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                mov EAX, dword ptr [bptr];
+                movq MM4, qword ptr [w];
+
+                align 8;
+            start3dnow:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfsub MM0, MM4;
+                pfsub MM1, MM4;
+                pfsub MM2, MM4;
+                pfsub MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+                mov dword ptr [bptr], EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ - value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMinSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = value - b[]
+ */
+
+T[] _arrayExpSliceMinSliceAssign_f(T[] a, T[] b, T value)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arrayExpSliceMinSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 690% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movaps XMM5, XMM4;
+                movaps XMM6, XMM4;
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                subps XMM5, XMM0;
+                subps XMM6, XMM1;
+                movups [ESI+ 0-64], XMM5;
+                movups [ESI+16-64], XMM6;
+                movaps XMM5, XMM4;
+                movaps XMM6, XMM4;
+                subps XMM5, XMM2;
+                subps XMM6, XMM3;
+                movups [ESI+32-64], XMM5;
+                movups [ESI+48-64], XMM6;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        // 3DNow! version is 67% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start3dnow:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfsubr MM0, MM4;
+                pfsubr MM1, MM4;
+                pfsubr MM2, MM4;
+                pfsubr MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = value - *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = 6 - a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(6 - a[i]))
+                {
+                    printf("[%d]: %g != 6 - %g\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= value
+ */
+
+T[] _arrayExpSliceMinass_f(T[] a, T value)
+{
+    //printf("_arrayExpSliceMinass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 304% faster
+        if (sse() && a.length >= 16)
+        {
+            // align pointer
+            auto n = cast(T*)((cast(uint)aptr + 15) & ~15);
+            while (aptr < n)
+                *aptr++ -= value;
+            n = cast(T*)((cast(uint)aend) & ~15);
+            if (aptr < n)
+
+            // Aligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movaps XMM0, [ESI];
+                movaps XMM1, [ESI+16];
+                movaps XMM2, [ESI+32];
+                movaps XMM3, [ESI+48];
+                add ESI, 64;
+                subps XMM0, XMM4;
+                subps XMM1, XMM4;
+                subps XMM2, XMM4;
+                subps XMM3, XMM4;
+                movaps [ESI+ 0-64], XMM0;
+                movaps [ESI+16-64], XMM1;
+                movaps [ESI+32-64], XMM2;
+                movaps [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+        else
+        // 3DNow! version is 63% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfsub MM0, MM4;
+                pfsub MM1, MM4;
+                pfsub MM2, MM4;
+                pfsub MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceminass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[]
+ */
+
+T[] _arraySliceSliceMinass_f(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMinass_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 468% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [ESI];
+                movups XMM1, [ESI+16];
+                movups XMM2, [ESI+32];
+                movups XMM3, [ESI+48];
+                add ESI, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add ECX, 64;
+                subps XMM0, XMM4;
+                subps XMM1, XMM5;
+                subps XMM2, XMM6;
+                subps XMM3, XMM7;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is 57% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr]; // destination operand
+                mov EDI, dword ptr [n]; // end comparison
+                mov ECX, dword ptr [bptr]; // right operand
+
+                align 4;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfsub MM0, [ECX];
+                pfsub MM1, [ECX+8];
+                pfsub MM2, [ECX+16];
+                pfsub MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add ECX, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAssign_f(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMulSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 607% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM4;
+                mulps XMM2, XMM4;
+                mulps XMM3, XMM4;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        // 3DNow! version is 69% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                mov EAX, dword ptr [bptr];
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfmul MM0, MM4;
+                pfmul MM1, MM4;
+                pfmul MM2, MM4;
+                pfmul MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * c[]
+ */
+
+T[] _arraySliceSliceMulSliceAssign_f(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceMulSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 833% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add ESI, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add EAX, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM5;
+                mulps XMM2, XMM6;
+                mulps XMM3, XMM7;
+                add ECX, 64;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is only 13% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr]; // destination operand
+                mov EDI, dword ptr [n]; // end comparison
+                mov EAX, dword ptr [bptr]; // left operand
+                mov ECX, dword ptr [cptr]; // right operand
+
+                align 4;
+            start:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfmul MM0, [ECX];
+                pfmul MM1, [ECX+8];
+                pfmul MM2, [ECX+16];
+                pfmul MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ECX, 32;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * *cptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * b[i]))
+                {
+                    printf("[%d]: %g != %g * %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= value
+ */
+
+T[] _arrayExpSliceMulass_f(T[] a, T value)
+{
+    //printf("_arrayExpSliceMulass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 303% faster
+        if (sse() && a.length >= 16)
+        {
+            // align pointer
+            auto n = cast(T*)((cast(uint)aptr + 15) & ~15);
+            while (aptr < n)
+                *aptr++ *= value;
+            n = cast(T*)((cast(uint)aend) & ~15);
+            if (aptr < n)
+
+            // Aligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movaps XMM0, [ESI];
+                movaps XMM1, [ESI+16];
+                movaps XMM2, [ESI+32];
+                movaps XMM3, [ESI+48];
+                add ESI, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM4;
+                mulps XMM2, XMM4;
+                mulps XMM3, XMM4;
+                movaps [ESI+ 0-64], XMM0;
+                movaps [ESI+16-64], XMM1;
+                movaps [ESI+32-64], XMM2;
+                movaps [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+        else
+        // 3DNow! version is 63% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfmul MM0, MM4;
+                pfmul MM1, MM4;
+                pfmul MM2, MM4;
+                pfmul MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= b[]
+ */
+
+T[] _arraySliceSliceMulass_f(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMulass_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 525% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [ESI];
+                movups XMM1, [ESI+16];
+                movups XMM2, [ESI+32];
+                movups XMM3, [ESI+48];
+                add ESI, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add ECX, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM5;
+                mulps XMM2, XMM6;
+                mulps XMM3, XMM7;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is 57% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr]; // destination operand
+                mov EDI, dword ptr [n]; // end comparison
+                mov ECX, dword ptr [bptr]; // right operand
+
+                align 4;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfmul MM0, [ECX];
+                pfmul MM1, [ECX+8];
+                pfmul MM2, [ECX+16];
+                pfmul MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add ECX, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+                mov dword ptr [bptr], ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] / value
+ */
+
+T[] _arraySliceExpDivSliceAssign_f(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpDivSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    /* Multiplying by the reciprocal is faster, but does
+     * not produce as accurate an answer.
+     */
+    T recip = cast(T)1 / value;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 587% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, recip;
+                //movss XMM4, value
+                //rcpss XMM4, XMM4
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM4;
+                mulps XMM2, XMM4;
+                mulps XMM3, XMM4;
+                //divps XMM0, XMM4;
+                //divps XMM1, XMM4;
+                //divps XMM2, XMM4;
+                //divps XMM3, XMM4;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        // 3DNow! version is 72% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            T[2] w = void;
+
+            w[0] = recip;
+            w[1] = recip;
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                mov EAX, dword ptr [bptr];
+                movq MM4, qword ptr [w];
+
+                align 8;
+            start:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfmul MM0, MM4;
+                pfmul MM1, MM4;
+                pfmul MM2, MM4;
+                pfmul MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+                mov dword ptr [bptr], EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * recip;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpDivSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] / 8;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] / 8))
+                {
+                    printf("[%d]: %g != %g / 8\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] /= value
+ */
+
+T[] _arrayExpSliceDivass_f(T[] a, T value)
+{
+    //printf("_arrayExpSliceDivass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    /* Multiplying by the reciprocal is faster, but does
+     * not produce as accurate an answer.
+     */
+    T recip = cast(T)1 / value;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 245% faster
+        if (sse() && a.length >= 16)
+        {
+            // align pointer
+            auto n = cast(T*)((cast(uint)aptr + 15) & ~15);
+            while (aptr < n)
+                *aptr++ *= recip;
+            n = cast(T*)((cast(uint)aend) & ~15);
+            if (aptr < n)
+
+            // Aligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, recip;
+                //movss XMM4, value
+                //rcpss XMM4, XMM4
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movaps XMM0, [ESI];
+                movaps XMM1, [ESI+16];
+                movaps XMM2, [ESI+32];
+                movaps XMM3, [ESI+48];
+                add ESI, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM4;
+                mulps XMM2, XMM4;
+                mulps XMM3, XMM4;
+                //divps XMM0, XMM4;
+                //divps XMM1, XMM4;
+                //divps XMM2, XMM4;
+                //divps XMM3, XMM4;
+                movaps [ESI+ 0-64], XMM0;
+                movaps [ESI+16-64], XMM1;
+                movaps [ESI+32-64], XMM2;
+                movaps [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+        else
+        // 3DNow! version is 57% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            T[2] w = void;
+
+            w[0] = w[1] = recip;
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                movq MM4, qword ptr [w];
+
+                align 8;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfmul MM0, MM4;
+                pfmul MM1, MM4;
+                pfmul MM2, MM4;
+                pfmul MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= recip;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceDivass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] /= 8;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] / 8))
+                {
+                    printf("[%d]: %g != %g / 8\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[] * value
+ */
+
+T[] _arraySliceExpMulSliceMinass_f(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAddass_f(a, -value, b);
+}
+
+/***********************
+ * Computes:
+ *      a[] += b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAddass_f(T[] a, T value, T[] b)
+in
+{
+        assert(a.length == b.length);
+        assert(disjoint(a, b));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ += *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAddass_f unittest\n");
+
+    cpuid = 1;
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 1; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] += a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                //printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]);
+                if (c[i] != cast(T)(b[i] + a[i] * 6))
+                {
+                    printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/arrayint.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,2430 @@
+/**
+ * Contains MMX versions of certain operations for dchar, int, and uint ('w',
+ * 'i' and 'k' suffixes).
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arrayint;
+
+private import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 4;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.amd3dnow amd3dnow;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+alias int T;
+
+extern (C):
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + value
+ */
+
+T[] _arraySliceExpAddSliceAssign_w(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_k(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_i(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpAddSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 380% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 298% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                paddd MM0, MM2;
+                paddd MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        if (a.length >= 2)
+        {
+            auto n = aptr + (a.length & ~1);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov EDX, value;
+
+                align 4;
+            start386:
+                add ESI, 8;
+                mov EBX, [EAX];
+                mov ECX, [EAX+4];
+                add EAX, 8;
+                add EBX, EDX;
+                add ECX, EDX;
+                mov [ESI  -8], EBX;
+                mov [ESI+4-8], ECX;
+                cmp ESI, EDI;
+                jb start386;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ + value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpAddSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_w(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_k(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_i(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceAddSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1710% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 995% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM2, [ECX];
+                movq MM1, [EAX+8];
+                movq MM3, [ECX+8];
+                add EAX, 16;
+                add ECX, 16;
+                paddd MM0, MM2;
+                paddd MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+normal:
+    while (aptr < aend)
+        *aptr++ = *bptr++ + *cptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += value
+ */
+
+T[] _arrayExpSliceAddass_w(T[] a, T value)
+{
+    return _arrayExpSliceAddass_i(a, value);
+}
+
+T[] _arrayExpSliceAddass_k(T[] a, T value)
+{
+    return _arrayExpSliceAddass_i(a, value);
+}
+
+T[] _arrayExpSliceAddass_i(T[] a, T value)
+{
+    //printf("_arrayExpSliceAddass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 83% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 81% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                paddd MM0, MM2;
+                paddd MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+        else
+        if (a.length >= 2)
+        {
+            auto n = aptr + (a.length & ~1);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EDX, value;
+
+                align 4;
+            start386:
+                mov EBX, [ESI];
+                mov ECX, [ESI+4];
+                add ESI, 8;
+                add EBX, EDX;
+                add ECX, EDX;
+                mov [ESI  -8], EBX;
+                mov [ESI+4-8], ECX;
+                cmp ESI, EDI;
+                jb start386;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceAddass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            a[] += 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(c[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, a[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += b[]
+ */
+
+T[] _arraySliceSliceAddass_w(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_i(a, b);
+}
+
+T[] _arraySliceSliceAddass_k(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_i(a, b);
+}
+
+T[] _arraySliceSliceAddass_i(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceAddass_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 695% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 471% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM2, [ECX];
+                movq MM1, [ESI+8];
+                movq MM3, [ECX+8];
+                add ESI, 16;
+                add ECX, 16;
+                paddd MM0, MM2;
+                paddd MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+normal:
+    while (aptr < aend)
+        *aptr++ += *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] += a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(b[i] + a[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - value
+ */
+
+T[] _arraySliceExpMinSliceAssign_w(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_k(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_i(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMinSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 400% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 315% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                psubd MM0, MM2;
+                psubd MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        if (a.length >= 2)
+        {
+            auto n = aptr + (a.length & ~1);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov EDX, value;
+
+                align 4;
+            start386:
+                add ESI, 8;
+                mov EBX, [EAX];
+                mov ECX, [EAX+4];
+                add EAX, 8;
+                sub EBX, EDX;
+                sub ECX, EDX;
+                mov [ESI  -8], EBX;
+                mov [ESI+4-8], ECX;
+                cmp ESI, EDI;
+                jb start386;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ - value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMinSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = value - b[]
+ */
+
+T[] _arrayExpSliceMinSliceAssign_w(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_i(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_k(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_i(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_i(T[] a, T[] b, T value)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arrayExpSliceMinSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1812% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 4;
+                startaddsse2u:
+                    add ESI, 32;
+                    movdqu XMM2, [EAX];
+                    movdqu XMM3, [EAX+16];
+                    movdqa XMM0, XMM4;
+                    movdqa XMM1, XMM4;
+                    add EAX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 4;
+                startaddsse2a:
+                    add ESI, 32;
+                    movdqa XMM2, [EAX];
+                    movdqa XMM3, [EAX+16];
+                    movdqa XMM0, XMM4;
+                    movdqa XMM1, XMM4;
+                    add EAX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 1077% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM4, l;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM2, [EAX];
+                movq MM3, [EAX+8];
+                movq MM0, MM4;
+                movq MM1, MM4;
+                add EAX, 16;
+                psubd MM0, MM2;
+                psubd MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = value - *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = 6 - a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(6 - a[i]))
+                {
+                    printf("[%d]: %d != 6 - %d\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_w(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_k(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_i(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1721% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 1002% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM2, [ECX];
+                movq MM1, [EAX+8];
+                movq MM3, [ECX+8];
+                add EAX, 16;
+                add ECX, 16;
+                psubd MM0, MM2;
+                psubd MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ - *cptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= value
+ */
+
+T[] _arrayExpSliceMinass_w(T[] a, T value)
+{
+    return _arrayExpSliceMinass_i(a, value);
+}
+
+T[] _arrayExpSliceMinass_k(T[] a, T value)
+{
+    return _arrayExpSliceMinass_i(a, value);
+}
+
+T[] _arrayExpSliceMinass_i(T[] a, T value)
+{
+    //printf("_arrayExpSliceMinass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 81% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 81% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                psubd MM0, MM2;
+                psubd MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+        else
+        if (a.length >= 2)
+        {
+            auto n = aptr + (a.length & ~1);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EDX, value;
+
+                align 4;
+            start386:
+                mov EBX, [ESI];
+                mov ECX, [ESI+4];
+                add ESI, 8;
+                sub EBX, EDX;
+                sub ECX, EDX;
+                mov [ESI  -8], EBX;
+                mov [ESI+4-8], ECX;
+                cmp ESI, EDI;
+                jb start386;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            a[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(c[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, a[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[]
+ */
+
+T[] _arraySliceSliceMinass_w(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_i(a, b);
+}
+
+T[] _arraySliceSliceMinass_k(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_i(a, b);
+}
+
+T[] _arraySliceSliceMinass_i(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMinass_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 731% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 441% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM2, [ECX];
+                movq MM1, [ESI+8];
+                movq MM3, [ECX+8];
+                add ESI, 16;
+                add ECX, 16;
+                psubd MM0, MM2;
+                psubd MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] -= a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(b[i] - a[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAssign_w(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpMulSliceAssign_k(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpMulSliceAssign_i(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMulSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+  version (none)        // multiplying a pair is not supported by MMX
+  {
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1380% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        {
+        // MMX version is 1380% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                pmuludq MM0, MM2;       // only multiplies low 32 bits
+                pmuludq MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+        }
+  }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                //printf("[%d]: %d ?= %d * 6\n", i, c[i], a[i]);
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %d != %d * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * c[]
+ */
+
+T[] _arraySliceSliceMulSliceAssign_w(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMulSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceMulSliceAssign_k(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMulSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceMulSliceAssign_i(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceMulSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+  version (none)
+  {
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1407% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+               }
+            }
+        }
+        else
+        // MMX version is 1029% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM2, [ECX];
+                movq MM1, [EAX+8];
+                movq MM3, [ECX+8];
+                add EAX, 16;
+                add ECX, 16;
+                pmuludq MM0, MM2;
+                pmuludq MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+  }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * *cptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * b[i]))
+                {
+                    printf("[%d]: %d != %d * %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= value
+ */
+
+T[] _arrayExpSliceMulass_w(T[] a, T value)
+{
+    return _arrayExpSliceMulass_i(a, value);
+}
+
+T[] _arrayExpSliceMulass_k(T[] a, T value)
+{
+    return _arrayExpSliceMulass_i(a, value);
+}
+
+T[] _arrayExpSliceMulass_i(T[] a, T value)
+{
+    //printf("_arrayExpSliceMulass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+  version (none)
+  {
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 400% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 402% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                pmuludq MM0, MM2;
+                pmuludq MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+  }
+
+    while (aptr < aend)
+        *aptr++ *= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = a[];
+            a[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(b[i] * 6))
+                {
+                    printf("[%d]: %d != %d * 6\n", i, a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= b[]
+ */
+
+T[] _arraySliceSliceMulass_w(T[] a, T[] b)
+{
+    return _arraySliceSliceMulass_i(a, b);
+}
+
+T[] _arraySliceSliceMulass_k(T[] a, T[] b)
+{
+    return _arraySliceSliceMulass_i(a, b);
+}
+
+T[] _arraySliceSliceMulass_i(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMulass_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+  version (none)
+  {
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 873% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+               }
+            }
+        }
+/+ BUG: comment out this section until we figure out what is going
+   wrong with the invalid pshufd instructions.
+
+        else
+        // MMX version is 573% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM2, [ECX];
+                movq MM1, [ESI+8];
+                movq MM3, [ECX+8];
+                pxor MM4, MM4;
+                pxor MM5, MM5;
+                punpckldq MM4, MM0;
+                punpckldq MM5, MM2;
+                add ESI, 16;
+                add ECX, 16;
+                pmuludq MM4, MM5;
+                pshufd MM4, MM4, 8;     // ?
+                movq [ESI  -16], MM4;
+                pxor MM4, MM4;
+                pxor MM5, MM5;
+                punpckldq MM4, MM1;
+                punpckldq MM5, MM3;
+                pmuludq MM4, MM5;
+                pshufd MM4, MM4, 8;     // ?
+                movq [ESI+8-16], MM4;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
++/
+    }
+  }
+
+    while (aptr < aend)
+        *aptr++ *= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = a[];
+            a[] *= c[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(b[i] * c[i]))
+                {
+                    printf("[%d]: %d != %d * %d\n", i, a[i], b[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/arrayreal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,241 @@
+/**
+ * Contains SSE2 and MMX versions of certain operations for real.
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arrayreal;
+
+import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 1;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.amd3dnow amd3dnow;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+alias real T;
+
+extern (C):
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_r(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    for (int i = 0; i < a.length; i++)
+        a[i] = b[i] + c[i];
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_r unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %Lg != %Lg + %Lg\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_r(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    for (int i = 0; i < a.length; i++)
+        a[i] = b[i] - c[i];
+    return a;
+}
+
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_r unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %Lg != %Lg - %Lg\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[] * value
+ */
+
+T[] _arraySliceExpMulSliceMinass_r(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAddass_r(a, -value, b);
+}
+
+/***********************
+ * Computes:
+ *      a[] += b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAddass_r(T[] a, T value, T[] b)
+in
+{
+        assert(a.length == b.length);
+        assert(disjoint(a, b));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ += *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAddass_r unittest\n");
+
+    cpuid = 1;
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 1; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] += a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                //printf("[%d]: %Lg ?= %Lg + %Lg * 6\n", i, c[i], b[i], a[i]);
+                if (c[i] != cast(T)(b[i] + a[i] * 6))
+                {
+                    printf("[%d]: %Lg ?= %Lg + %Lg * 6\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/arrayshort.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,2303 @@
+/**
+ * Contains SSE2 and MMX versions of certain operations for wchar, short,
+ * and ushort ('u', 's' and 't' suffixes).
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arrayshort;
+
+private import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 4;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.sse2 sse2;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+alias short T;
+
+extern (C):
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + value
+ */
+
+T[] _arraySliceExpAddSliceAssign_u(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_t(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_s(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpAddSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 3343% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 3343% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                paddw MM0, MM2;
+                paddw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ + value);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpAddSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_u(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_t(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_s(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceAddSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 3777% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    movdqu XMM2, [ECX];
+                    movdqu XMM3, [ECX+16];
+                    add ECX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    movdqa XMM2, [ECX];
+                    movdqa XMM3, [ECX+16];
+                    add ECX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 2068% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                movq MM2, [ECX];
+                movq MM3, [ECX+8];
+                add ECX, 16;
+                paddw MM0, MM2;
+                paddw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ + *cptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += value
+ */
+
+T[] _arrayExpSliceAddass_u(T[] a, T value)
+{
+    return _arrayExpSliceAddass_s(a, value);
+}
+
+T[] _arrayExpSliceAddass_t(T[] a, T value)
+{
+    return _arrayExpSliceAddass_s(a, value);
+}
+
+T[] _arrayExpSliceAddass_s(T[] a, T value)
+{
+    //printf("_arrayExpSliceAddass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 832% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= (l << 16);
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 826% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                paddw MM0, MM2;
+                paddw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceAddass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            a[] += 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(c[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, a[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += b[]
+ */
+
+T[] _arraySliceSliceAddass_u(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_s(a, b);
+}
+
+T[] _arraySliceSliceAddass_t(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_s(a, b);
+}
+
+T[] _arraySliceSliceAddass_s(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceAddass_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 2085% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    movdqu XMM2, [ECX];
+                    movdqu XMM3, [ECX+16];
+                    add ECX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    movdqa XMM2, [ECX];
+                    movdqa XMM3, [ECX+16];
+                    add ECX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 1022% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                movq MM2, [ECX];
+                movq MM3, [ECX+8];
+                add ECX, 16;
+                paddw MM0, MM2;
+                paddw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] += a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(b[i] + a[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - value
+ */
+
+T[] _arraySliceExpMinSliceAssign_u(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_t(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_s(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMinSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 3695% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 3049% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                psubw MM0, MM2;
+                psubw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ - value);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMinSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = value - b[]
+ */
+
+T[] _arrayExpSliceMinSliceAssign_u(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_s(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_t(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_s(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_s(T[] a, T[] b, T value)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arrayExpSliceMinSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 4995% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+
+                    align 4;
+                startaddsse2u:
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+                    movd XMM3, l;
+                    pshufd XMM3, XMM3, 0;
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubw XMM2, XMM0;
+                    psubw XMM3, XMM1;
+                    movdqu [ESI   -32], XMM2;
+                    movdqu [ESI+16-32], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+
+                    align 4;
+                startaddsse2a:
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+                    movd XMM3, l;
+                    pshufd XMM3, XMM3, 0;
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubw XMM2, XMM0;
+                    psubw XMM3, XMM1;
+                    movdqa [ESI   -32], XMM2;
+                    movdqa [ESI+16-32], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 4562% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM2, [EAX];
+                movq MM3, [EAX+8];
+                movq MM0, MM4;
+                movq MM1, MM4;
+                add EAX, 16;
+                psubw MM0, MM2;
+                psubw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(value - *bptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = 6 - a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(6 - a[i]))
+                {
+                    printf("[%d]: %d != 6 - %d\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_u(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_t(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_s(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 4129% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    movdqu XMM2, [ECX];
+                    movdqu XMM3, [ECX+16];
+                    add ECX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    movdqa XMM2, [ECX];
+                    movdqa XMM3, [ECX+16];
+                    add ECX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 2018% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                movq MM2, [ECX];
+                movq MM3, [ECX+8];
+                add ECX, 16;
+                psubw MM0, MM2;
+                psubw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ - *cptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= value
+ */
+
+T[] _arrayExpSliceMinass_u(T[] a, T value)
+{
+    return _arrayExpSliceMinass_s(a, value);
+}
+
+T[] _arrayExpSliceMinass_t(T[] a, T value)
+{
+    return _arrayExpSliceMinass_s(a, value);
+}
+
+T[] _arrayExpSliceMinass_s(T[] a, T value)
+{
+    //printf("_arrayExpSliceMinass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 835% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= (l << 16);
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 835% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                psubw MM0, MM2;
+                psubw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            a[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(c[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, a[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[]
+ */
+
+T[] _arraySliceSliceMinass_u(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_s(a, b);
+}
+
+T[] _arraySliceSliceMinass_t(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_s(a, b);
+}
+
+T[] _arraySliceSliceMinass_s(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMinass_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 2121% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    movdqu XMM2, [ECX];
+                    movdqu XMM3, [ECX+16];
+                    add ECX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    movdqa XMM2, [ECX];
+                    movdqa XMM3, [ECX+16];
+                    add ECX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 1116% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                movq MM2, [ECX];
+                movq MM3, [ECX+8];
+                add ECX, 16;
+                psubw MM0, MM2;
+                psubw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] -= a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(b[i] - a[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAssign_u(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpMulSliceAssign_t(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpMulSliceAssign_s(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMulSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 3733% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= l << 16;
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 3733% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                pmullw MM0, MM2;
+                pmullw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ * value);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %d != %d * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * c[]
+ */
+
+T[] _arraySliceSliceMulSliceAssign_u(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMulSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceMulSliceAssign_t(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMulSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceMulSliceAssign_s(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceMulSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 2515% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+               }
+            }
+        }
+        else
+        // MMX version is 2515% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM2, [ECX];
+                movq MM1, [EAX+8];
+                movq MM3, [ECX+8];
+                add EAX, 16;
+                add ECX, 16;
+                pmullw MM0, MM2;
+                pmullw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ * *cptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * b[i]))
+                {
+                    printf("[%d]: %d != %d * %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= value
+ */
+
+T[] _arrayExpSliceMulass_u(T[] a, T value)
+{
+    return _arrayExpSliceMulass_s(a, value);
+}
+
+T[] _arrayExpSliceMulass_t(T[] a, T value)
+{
+    return _arrayExpSliceMulass_s(a, value);
+}
+
+T[] _arrayExpSliceMulass_s(T[] a, T value)
+{
+    //printf("_arrayExpSliceMulass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 2044% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= l << 16;
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 2056% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                pmullw MM0, MM2;
+                pmullw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = a[];
+            a[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(b[i] * 6))
+                {
+                    printf("[%d]: %d != %d * 6\n", i, a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= b[]
+ */
+
+T[] _arraySliceSliceMulass_u(T[] a, T[] b)
+{
+    return _arraySliceSliceMulass_s(a, b);
+}
+
+T[] _arraySliceSliceMulass_t(T[] a, T[] b)
+{
+    return _arraySliceSliceMulass_s(a, b);
+}
+
+T[] _arraySliceSliceMulass_s(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMulass_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 2519% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+               }
+            }
+        }
+        else
+        // MMX version is 1712% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM2, [ECX];
+                movq MM1, [ESI+8];
+                movq MM3, [ECX+8];
+                add ESI, 16;
+                add ECX, 16;
+                pmullw MM0, MM2;
+                pmullw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = a[];
+            a[] *= c[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(b[i] * c[i]))
+                {
+                    printf("[%d]: %d != %d * %d\n", i, a[i], b[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/cast_.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,169 @@
+/**
+ * Implementation of array assignment support routines.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.cast_;
+
+extern (C):
+
+/******************************************
+ * Given a pointer:
+ *      If it is an Object, return that Object.
+ *      If it is an interface, return the Object implementing the interface.
+ *      If it is null, return null.
+ *      Else, undefined crash
+ */
+
+Object _d_toObject(void* p)
+{   Object o;
+
+    if (p)
+    {
+        o = cast(Object)p;
+        ClassInfo oc = o.classinfo;
+        Interface *pi = **cast(Interface ***)p;
+
+        /* Interface.offset lines up with ClassInfo.name.ptr,
+         * so we rely on pointers never being less than 64K,
+         * and Objects never being greater.
+         */
+        if (pi.offset < 0x10000)
+        {
+            //printf("\tpi.offset = %d\n", pi.offset);
+            o = cast(Object)(p - pi.offset);
+        }
+    }
+    return o;
+}
+
+
+/*************************************
+ * Attempts to cast Object o to class c.
+ * Returns o if successful, null if not.
+ */
+
+Object _d_interface_cast(void* p, ClassInfo c)
+{   Object o;
+
+    //printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
+    if (p)
+    {
+        Interface *pi = **cast(Interface ***)p;
+
+        //printf("\tpi.offset = %d\n", pi.offset);
+        o = cast(Object)(p - pi.offset);
+        return _d_dynamic_cast(o, c);
+    }
+    return o;
+}
+
+Object _d_dynamic_cast(Object o, ClassInfo c)
+{   ClassInfo oc;
+    size_t offset = 0;
+
+    //printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
+
+    if (o)
+    {
+        oc = o.classinfo;
+        if (_d_isbaseof2(oc, c, offset))
+        {
+            //printf("\toffset = %d\n", offset);
+            o = cast(Object)(cast(void*)o + offset);
+        }
+        else
+            o = null;
+    }
+    //printf("\tresult = %p\n", o);
+    return o;
+}
+
+int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout size_t offset)
+{   int i;
+
+    if (oc is c)
+        return 1;
+    do
+    {
+        if (oc.base is c)
+            return 1;
+        for (i = 0; i < oc.interfaces.length; i++)
+        {
+            ClassInfo ic;
+
+            ic = oc.interfaces[i].classinfo;
+            if (ic is c)
+            {   offset = oc.interfaces[i].offset;
+                return 1;
+            }
+        }
+        for (i = 0; i < oc.interfaces.length; i++)
+        {
+            ClassInfo ic;
+
+            ic = oc.interfaces[i].classinfo;
+            if (_d_isbaseof2(ic, c, offset))
+            {   offset = oc.interfaces[i].offset;
+                return 1;
+            }
+        }
+        oc = oc.base;
+    } while (oc);
+    return 0;
+}
+
+int _d_isbaseof(ClassInfo oc, ClassInfo c)
+{   int i;
+
+    if (oc is c)
+        return 1;
+    do
+    {
+        if (oc.base is c)
+            return 1;
+        for (i = 0; i < oc.interfaces.length; i++)
+        {
+            ClassInfo ic;
+
+            ic = oc.interfaces[i].classinfo;
+            if (ic is c || _d_isbaseof(ic, c))
+                return 1;
+        }
+        oc = oc.base;
+    } while (oc);
+    return 0;
+}
+
+/*********************************
+ * Find the vtbl[] associated with Interface ic.
+ */
+
+void *_d_interface_vtbl(ClassInfo ic, Object o)
+{   int i;
+    ClassInfo oc;
+
+    //printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
+
+    assert(o);
+
+    oc = o.classinfo;
+    for (i = 0; i < oc.interfaces.length; i++)
+    {
+        ClassInfo oic;
+
+        oic = oc.interfaces[i].classinfo;
+        if (oic is ic)
+        {
+            return cast(void *)oc.interfaces[i].vtbl;
+        }
+    }
+    assert(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/cmath2.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,218 @@
+/**
+ * Runtime support for complex arithmetic code generation (for Posix).
+ *
+ * Copyright: Copyright Digital Mars 2001 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2001 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.cmath2;
+
+private import core.stdc.math;
+
+extern (C):
+
+/****************************
+ * Multiply two complex floating point numbers, x and y.
+ * Input:
+ *      x.re    ST3
+ *      x.im    ST2
+ *      y.re    ST1
+ *      y.im    ST0
+ * Output:
+ *      ST1     real part
+ *      ST0     imaginary part
+ */
+
+void _Cmul()
+{
+    // p.re = x.re * y.re - x.im * y.im;
+    // p.im = x.im * y.re + x.re * y.im;
+    asm
+    {   naked                   ;
+        fld     ST(1)           ; // x.re
+        fmul    ST,ST(4)        ; // ST0 = x.re * y.re
+
+        fld     ST(1)           ; // y.im
+        fmul    ST,ST(4)        ; // ST0 = x.im * y.im
+
+        fsubp   ST(1),ST        ; // ST0 = x.re * y.re - x.im * y.im
+
+        fld     ST(3)           ; // x.im
+        fmul    ST,ST(3)        ; // ST0 = x.im * y.re
+
+        fld     ST(5)           ; // x.re
+        fmul    ST,ST(3)        ; // ST0 = x.re * y.im
+
+        faddp   ST(1),ST        ; // ST0 = x.im * y.re + x.re * y.im
+
+        fxch    ST(4),ST        ;
+        fstp    ST(0)           ;
+        fxch    ST(4),ST        ;
+        fstp    ST(0)           ;
+        fstp    ST(0)           ;
+        fstp    ST(0)           ;
+
+        ret                     ;
+    }
+/+
+    if (isnan(x) && isnan(y))
+    {
+        // Recover infinities that computed as NaN+ iNaN ...
+        int recalc = 0;
+        if ( isinf( a) || isinf( b) )
+        {   // z is infinite
+            // "Box" the infinity and change NaNs in the other factor to 0
+            a = copysignl( isinf( a) ? 1.0 : 0.0, a);
+            b = copysignl( isinf( b) ? 1.0 : 0.0, b);
+            if (isnan( c)) c = copysignl( 0.0, c);
+            if (isnan( d)) d = copysignl( 0.0, d);
+            recalc = 1;
+        }
+        if (isinf(c) || isinf(d))
+        {   // w is infinite
+            // "Box" the infinity and change NaNs in the other factor to 0
+            c = copysignl( isinf( c) ? 1.0 : 0.0, c);
+            d = copysignl( isinf( d) ? 1.0 : 0.0, d);
+            if (isnan( a)) a = copysignl( 0.0, a);
+            if (isnan( b)) b = copysignl( 0.0, b);
+            recalc = 1;
+        }
+        if (!recalc && (isinf(ac) || isinf(bd) ||
+            isinf(ad) || isinf(bc)))
+        {
+            // Recover infinities from overflow by changing NaNs to 0 ...
+            if (isnan( a)) a = copysignl( 0.0, a);
+            if (isnan( b)) b = copysignl( 0.0, b);
+            if (isnan( c)) c = copysignl( 0.0, c);
+            if (isnan( d)) d = copysignl( 0.0, d);
+            recalc = 1;
+        }
+        if (recalc)
+        {
+            x = INFINITY * (a * c - b * d);
+            y = INFINITY * (a * d + b * c);
+        }
+    }
++/
+}
+
+/****************************
+ * Divide two complex floating point numbers, x / y.
+ * Input:
+ *      x.re    ST3
+ *      x.im    ST2
+ *      y.re    ST1
+ *      y.im    ST0
+ * Output:
+ *      ST1     real part
+ *      ST0     imaginary part
+ */
+
+void _Cdiv()
+{
+    real x_re, x_im;
+    real y_re, y_im;
+    real q_re, q_im;
+    real r;
+    real den;
+
+    asm
+    {
+        fstp    y_im    ;
+        fstp    y_re    ;
+        fstp    x_im    ;
+        fstp    x_re    ;
+    }
+
+    if (fabs(y_re) < fabs(y_im))
+    {
+        r = y_re / y_im;
+        den = y_im + r * y_re;
+        q_re = (x_re * r + x_im) / den;
+        q_im = (x_im * r - x_re) / den;
+    }
+    else
+    {
+        r = y_im / y_re;
+        den = y_re + r * y_im;
+        q_re = (x_re + r * x_im) / den;
+        q_im = (x_im - r * x_re) / den;
+    }
+//printf("q.re = %g, q.im = %g\n", (double)q_re, (double)q_im);
+/+
+    if (isnan(q_re) && isnan(q_im))
+    {
+        real denom = y_re * y_re + y_im * y_im;
+
+        // non-zero / zero
+        if (denom == 0.0 && (!isnan(x_re) || !isnan(x_im)))
+        {
+            q_re = copysignl(INFINITY, y_re) * x_re;
+            q_im = copysignl(INFINITY, y_re) * x_im;
+        }
+        // infinite / finite
+        else if ((isinf(x_re) || isinf(x_im)) && isfinite(y_re) && isfinite(y_im))
+        {
+            x_re = copysignl(isinf(x_re) ? 1.0 : 0.0, x_re);
+            x_im = copysignl(isinf(x_im) ? 1.0 : 0.0, x_im);
+            q_re = INFINITY * (x_re * y_re + x_im * y_im);
+            q_im = INFINITY * (x_im * y_re - x_re * y_im);
+        }
+        // finite / infinite
+        else if (isinf(logbw) && isfinite(x_re) && isfinite(x_im))
+        {
+            y_re = copysignl(isinf(y_re) ? 1.0 : 0.0, y_re);
+            y_im = copysignl(isinf(y_im) ? 1.0 : 0.0, y_im);
+            q_re = 0.0 * (x_re * y_re + x_im * y_im);
+            q_im = 0.0 * (x_im * y_re - x_re * y_im);
+        }
+    }
+    return q_re + q_im * 1.0i;
++/
+    asm
+    {
+        fld     q_re;
+        fld     q_im;
+    }
+}
+
+/****************************
+ * Compare two complex floating point numbers, x and y.
+ * Input:
+ *      x.re    ST3
+ *      x.im    ST2
+ *      y.re    ST1
+ *      y.im    ST0
+ * Output:
+ *      8087 stack is cleared
+ *      flags set
+ */
+
+void _Ccmp()
+{
+    asm
+    {   naked                   ;
+        fucomp  ST(2)           ; // compare x.im and y.im
+        fstsw   AX              ;
+        sahf                    ;
+        jne     L1              ;
+        jp      L1              ; // jmp if NAN
+        fucomp  ST(2)           ; // compare x.re and y.re
+        fstsw   AX              ;
+        sahf                    ;
+        fstp    ST(0)           ; // pop
+        fstp    ST(0)           ; // pop
+        ret                     ;
+
+      L1:
+        fstp    ST(0)           ; // pop
+        fstp    ST(0)           ; // pop
+        fstp    ST(0)           ; // pop
+        ret                     ;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/compiler.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,42 @@
+/**
+ * Compiler information and associated routines.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.compiler;
+
+// Identify the compiler used and its various features.
+
+const
+{
+    // Vendor specific string naming the compiler
+    char[] name = "Digital Mars D";
+
+    // Master list of D compiler vendors
+    enum Vendor
+    {
+        DigitalMars = 1
+    }
+
+    // Which vendor we are
+    Vendor vendor = Vendor.DigitalMars;
+
+
+    // The vendor specific version number, as in
+    // version_major.version_minor
+    uint version_major = 0;
+    uint version_minor = 0;
+
+
+    // The version of the D Programming Language Specification
+    // Supported by the compiler
+    uint D_major = 0;
+    uint D_minor = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/complex.c	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,112 @@
+/**
+ * Implementation of complex number support routines.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#include <math.h>
+
+typedef struct Complex
+{
+    long double re;
+    long double im;
+} Complex;
+
+Complex _complex_div(Complex x, Complex y)
+{
+    Complex q;
+    long double r;
+    long double den;
+
+    if (fabs(y.re) < fabs(y.im))
+    {
+        r = y.re / y.im;
+        den = y.im + r * y.re;
+        q.re = (x.re * r + x.im) / den;
+        q.im = (x.im * r - x.re) / den;
+    }
+    else
+    {
+        r = y.im / y.re;
+        den = y.re + r * y.im;
+        q.re = (x.re + r * x.im) / den;
+        q.im = (x.im - r * x.re) / den;
+    }
+    return q;
+}
+
+Complex _complex_mul(Complex x, Complex y)
+{
+    Complex p;
+
+    p.re = x.re * y.re - x.im * y.im;
+    p.im = x.im * y.re + x.re * y.im;
+    return p;
+}
+
+long double _complex_abs(Complex z)
+{
+    long double x,y,ans,temp;
+
+    x = fabs(z.re);
+    y = fabs(z.im);
+    if (x == 0)
+        ans = y;
+    else if (y == 0)
+        ans = x;
+    else if (x > y)
+    {
+        temp = y / x;
+        ans = x * sqrt(1 + temp * temp);
+    }
+    else
+    {
+        temp = x / y;
+        ans = y * sqrt(1 + temp * temp);
+    }
+    return ans;
+}
+
+Complex _complex_sqrt(Complex z)
+{
+    Complex c;
+    long double x,y,w,r;
+
+    if (z.re == 0 && z.im == 0)
+    {
+        c.re = 0;
+        c.im = 0;
+    }
+    else
+    {
+        x = fabs(z.re);
+        y = fabs(z.im);
+        if (x >= y)
+        {
+            r = y / x;
+            w = sqrt(x) * sqrt(0.5 * (1 + sqrt(1 + r * r)));
+        }
+        else
+        {
+            r = x / y;
+            w = sqrt(y) * sqrt(0.5 * (r + sqrt(1 + r * r)));
+        }
+        if (z.re >= 0)
+        {
+            c.re = w;
+            c.im = z.im / (w + w);
+        }
+        else
+        {
+            c.im = (z.im >= 0) ? w : -w;
+            c.re = z.im / (c.im + c.im);
+        }
+    }
+    return c;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/cover.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,463 @@
+/**
+ * Implementation of code coverage analyzer.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.cover;
+
+private
+{
+    version( Windows )
+        import core.sys.windows.windows;
+    else version( Posix )
+    {
+        import core.sys.posix.fcntl;
+        import core.sys.posix.unistd;
+    }
+    import core.bitop;
+    import core.stdc.stdio;
+    import rt.util.utf;
+
+    struct BitArray
+    {
+        size_t  len;
+        uint*   ptr;
+
+        bool opIndex( size_t i )
+        in
+        {
+            assert( i < len );
+        }
+        body
+        {
+            return cast(bool) bt( ptr, i );
+        }
+    }
+
+    struct Cover
+    {
+        string      filename;
+        BitArray    valid;
+        uint[]      data;
+    }
+
+    __gshared
+    {
+	Cover[] gdata;
+	string  srcpath;
+	string  dstpath;
+	bool    merge;
+    }
+}
+
+
+/**
+ * Set path to where source files are located.
+ *
+ * Params:
+ *  pathname = The new path name.
+ */
+extern (C) void dmd_coverSourcePath( string pathname )
+{
+    srcpath = pathname;
+}
+
+
+/**
+ * Set path to where listing files are to be written.
+ *
+ * Params:
+ *  pathname = The new path name.
+ */
+extern (C) void dmd_coverDestPath( string pathname )
+{
+    dstpath = pathname;
+}
+
+
+/**
+ * Set merge mode.
+ *
+ * Params:
+ *      flag = true means new data is summed with existing data in the listing
+ *         file; false means a new listing file is always created.
+ */
+extern (C) void dmd_coverSetMerge( bool flag )
+{
+    merge = flag;
+}
+
+
+/**
+ * The coverage callback.
+ *
+ * Params:
+ *  filename = The name of the coverage file.
+ *  valid    = ???
+ *  data     = ???
+ */
+extern (C) void _d_cover_register( string filename, BitArray valid, uint[] data )
+{
+    Cover c;
+
+    c.filename  = filename;
+    c.valid     = valid;
+    c.data      = data;
+    gdata      ~= c;
+}
+
+
+static ~this()
+{
+    const NUMLINES = 16384 - 1;
+    const NUMCHARS = 16384 * 16 - 1;
+
+    char[]      srcbuf      = new char[NUMCHARS];
+    char[][]    srclines    = new char[][NUMLINES];
+    char[]      lstbuf      = new char[NUMCHARS];
+    char[][]    lstlines    = new char[][NUMLINES];
+
+    foreach( Cover c; gdata )
+    {
+        if( !readFile( appendFN( srcpath, c.filename ), srcbuf ) )
+            continue;
+        splitLines( srcbuf, srclines );
+
+        if( merge )
+        {
+            if( !readFile( addExt( baseName( c.filename ), "lst" ), lstbuf ) )
+                break;
+            splitLines( lstbuf, lstlines );
+
+            for( size_t i = 0; i < lstlines.length; ++i )
+            {
+                if( i >= c.data.length )
+                    break;
+
+                int count = 0;
+
+                foreach( char c2; lstlines[i] )
+                {
+                    switch( c2 )
+                    {
+                    case ' ':
+                        continue;
+                    case '0': case '1': case '2': case '3': case '4':
+                    case '5': case '6': case '7': case '8': case '9':
+                        count = count * 10 + c2 - '0';
+                        continue;
+                    default:
+                        break;
+                    }
+                }
+                c.data[i] += count;
+            }
+        }
+
+        FILE* flst = fopen( (addExt( baseName( c.filename ), "lst\0" )).ptr, "wb" );
+
+        if( !flst )
+            continue; //throw new Exception( "Error opening file for write: " ~ lstfn );
+
+        uint nno;
+        uint nyes;
+
+        for( int i = 0; i < c.data.length; i++ )
+        {
+            if( i < srclines.length )
+            {
+                uint    n    = c.data[i];
+                char[]  line = srclines[i];
+
+                line = expandTabs( line );
+
+                if( n == 0 )
+                {
+                    if( c.valid[i] )
+                    {
+                        nno++;
+                        fprintf( flst, "0000000|%.*s\n", line );
+                    }
+                    else
+                    {
+                        fprintf( flst, "       |%.*s\n", line );
+                    }
+                }
+                else
+                {
+                    nyes++;
+                    fprintf( flst, "%7u|%.*s\n", n, line );
+                }
+            }
+        }
+        if( nyes + nno ) // no divide by 0 bugs
+        {
+            fprintf( flst, "%.*s is %d%% covered\n", c.filename, ( nyes * 100 ) / ( nyes + nno ) );
+        }
+        fclose( flst );
+    }
+}
+
+
+string appendFN( string path, string name )
+{
+    version( Windows )
+        const char sep = '\\';
+    else
+        const char sep = '/';
+
+    auto dest = path;
+
+    if( dest && dest[$ - 1] != sep )
+        dest ~= sep;
+    dest ~= name;
+    return dest;
+}
+
+
+string baseName( string name, string ext = null )
+{
+    auto i = name.length;
+    for( ; i > 0; --i )
+    {
+        version( Windows )
+        {
+            if( name[i - 1] == ':' || name[i - 1] == '\\' )
+                break;
+        }
+        else version( Posix )
+        {
+            if( name[i - 1] == '/' )
+                break;
+        }
+    }
+    return chomp( name[i .. $], ext ? ext : "" );
+}
+
+
+string getExt( string name )
+{
+    auto i = name.length;
+
+    while( i > 0 )
+    {
+        if( name[i - 1] == '.' )
+            return name[i .. $];
+        --i;
+        version( Windows )
+        {
+            if( name[i] == ':' || name[i] == '\\' )
+                break;
+        }
+        else version( Posix )
+        {
+            if( name[i] == '/' )
+                break;
+        }
+    }
+    return null;
+}
+
+
+string addExt( string name, string ext )
+{
+    auto  existing = getExt( name );
+
+    if( existing.length == 0 )
+    {
+        if( name.length && name[$ - 1] == '.' )
+            name ~= ext;
+        else
+            name = name ~ "." ~ ext;
+    }
+    else
+    {
+        name = name[0 .. $ - existing.length] ~ ext;
+    }
+    return name;
+}
+
+
+string chomp( string str, string delim = null )
+{
+    if( delim is null )
+    {
+        auto len = str.length;
+
+        if( len )
+        {
+            auto c = str[len - 1];
+
+            if( c == '\r' )
+                --len;
+            else if( c == '\n' && str[--len - 1] == '\r' )
+                --len;
+        }
+        return str[0 .. len];
+    }
+    else if( str.length >= delim.length )
+    {
+        if( str[$ - delim.length .. $] == delim )
+            return str[0 .. $ - delim.length];
+    }
+    return str;
+}
+
+
+bool readFile( string name, inout char[] buf )
+{
+    version( Windows )
+    {
+        auto    wnamez  = toUTF16z( name );
+        HANDLE  file    = CreateFileW( wnamez,
+                                       GENERIC_READ,
+                                       FILE_SHARE_READ,
+                                       null,
+                                       OPEN_EXISTING,
+                                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+                                       cast(HANDLE) null );
+
+        delete wnamez;
+        if( file == INVALID_HANDLE_VALUE )
+            return false;
+        scope( exit ) CloseHandle( file );
+
+        DWORD   num = 0;
+        DWORD   pos = 0;
+
+        buf.length = 4096;
+        while( true )
+        {
+            if( !ReadFile( file, &buf[pos], cast(DWORD)( buf.length - pos ), &num, null ) )
+                return false;
+            if( !num )
+                break;
+            pos += num;
+            buf.length = pos * 2;
+        }
+        buf.length = pos;
+        return true;
+    }
+    else version( Posix )
+    {
+        char[]  namez = new char[name.length + 1];
+                        namez[0 .. name.length] = name;
+                        namez[$ - 1] = 0;
+        int     file = open( namez.ptr, O_RDONLY );
+
+        delete namez;
+        if( file == -1 )
+            return false;
+        scope( exit ) close( file );
+
+        int     num = 0;
+        uint    pos = 0;
+
+        buf.length = 4096;
+        while( true )
+        {
+            num = read( file, &buf[pos], cast(uint)( buf.length - pos ) );
+            if( num == -1 )
+                return false;
+            if( !num )
+                break;
+            pos += num;
+            buf.length = pos * 2;
+        }
+        buf.length = pos;
+        return true;
+    }
+}
+
+
+void splitLines( char[] buf, inout char[][] lines )
+{
+    size_t  beg = 0,
+            pos = 0;
+
+    lines.length = 0;
+    for( ; pos < buf.length; ++pos )
+    {
+        char c = buf[pos];
+
+        switch( buf[pos] )
+        {
+        case '\r':
+        case '\n':
+            lines ~= buf[beg .. pos];
+            beg = pos + 1;
+            if( buf[pos] == '\r' && pos < buf.length - 1 && buf[pos + 1] == '\n' )
+                ++pos, ++beg;
+        default:
+            continue;
+        }
+    }
+    if( beg != pos )
+    {
+        lines ~= buf[beg .. pos];
+    }
+}
+
+
+char[] expandTabs( char[] str, int tabsize = 8 )
+{
+    const dchar LS = '\u2028'; // UTF line separator
+    const dchar PS = '\u2029'; // UTF paragraph separator
+
+    bool changes = false;
+    char[] result = str;
+    int column;
+    int nspaces;
+
+    foreach( size_t i, dchar c; str )
+    {
+        switch( c )
+        {
+            case '\t':
+                nspaces = tabsize - (column % tabsize);
+                if( !changes )
+                {
+                    changes = true;
+                    result = null;
+                    result.length = str.length + nspaces - 1;
+                    result.length = i + nspaces;
+                    result[0 .. i] = str[0 .. i];
+                    result[i .. i + nspaces] = ' ';
+                }
+                else
+                {   int j = result.length;
+                    result.length = j + nspaces;
+                    result[j .. j + nspaces] = ' ';
+                }
+                column += nspaces;
+                break;
+
+            case '\r':
+            case '\n':
+            case PS:
+            case LS:
+                column = 0;
+                goto L1;
+
+            default:
+                column++;
+            L1:
+                if (changes)
+                {
+                    if (c <= 0x7F)
+                        result ~= c;
+                    else
+                        encode(result, c);
+                }
+                break;
+        }
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/critical.c	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,173 @@
+/**
+ * Implementation of support routines for synchronized blocks.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/* ================================= Win32 ============================ */
+
+#if _WIN32
+
+#include <windows.h>
+
+/******************************************
+ * Enter/exit critical section.
+ */
+
+/* We don't initialize critical sections unless we actually need them.
+ * So keep a linked list of the ones we do use, and in the static destructor
+ * code, walk the list and release them.
+ */
+
+typedef struct D_CRITICAL_SECTION
+{
+    struct D_CRITICAL_SECTION *next;
+    CRITICAL_SECTION cs;
+} D_CRITICAL_SECTION;
+
+static D_CRITICAL_SECTION *dcs_list;
+static D_CRITICAL_SECTION critical_section;
+static volatile int inited;
+
+void _d_criticalenter(D_CRITICAL_SECTION *dcs)
+{
+    if (!dcs->next)
+    {
+        EnterCriticalSection(&critical_section.cs);
+        if (!dcs->next) // if, in the meantime, another thread didn't set it
+        {
+            dcs->next = dcs_list;
+            dcs_list = dcs;
+            InitializeCriticalSection(&dcs->cs);
+        }
+        LeaveCriticalSection(&critical_section.cs);
+    }
+    EnterCriticalSection(&dcs->cs);
+}
+
+void _d_criticalexit(D_CRITICAL_SECTION *dcs)
+{
+    LeaveCriticalSection(&dcs->cs);
+}
+
+void _STI_critical_init()
+{
+    if (!inited)
+    {   InitializeCriticalSection(&critical_section.cs);
+        dcs_list = &critical_section;
+        inited = 1;
+    }
+}
+
+void _STD_critical_term()
+{
+    if (inited)
+    {   inited = 0;
+        while (dcs_list)
+        {
+            DeleteCriticalSection(&dcs_list->cs);
+            dcs_list = dcs_list->next;
+        }
+    }
+}
+
+#endif
+
+/* ================================= linux ============================ */
+
+#if linux || __APPLE__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+// PTHREAD_MUTEX_RECURSIVE is the "standard" symbol,
+// while the _NP version is specific to Linux
+#ifndef PTHREAD_MUTEX_RECURSIVE
+#    define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
+#endif
+
+/******************************************
+ * Enter/exit critical section.
+ */
+
+/* We don't initialize critical sections unless we actually need them.
+ * So keep a linked list of the ones we do use, and in the static destructor
+ * code, walk the list and release them.
+ */
+
+typedef struct D_CRITICAL_SECTION
+{
+    struct D_CRITICAL_SECTION *next;
+    pthread_mutex_t cs;
+} D_CRITICAL_SECTION;
+
+static D_CRITICAL_SECTION *dcs_list;
+static D_CRITICAL_SECTION critical_section;
+static pthread_mutexattr_t _criticals_attr;
+
+void _STI_critical_init(void);
+void _STD_critical_term(void);
+
+void _d_criticalenter(D_CRITICAL_SECTION *dcs)
+{
+    if (!dcs_list)
+    {   _STI_critical_init();
+        atexit(_STD_critical_term);
+    }
+    //printf("_d_criticalenter(dcs = x%x)\n", dcs);
+    if (!dcs->next)
+    {
+        pthread_mutex_lock(&critical_section.cs);
+        if (!dcs->next) // if, in the meantime, another thread didn't set it
+        {
+            dcs->next = dcs_list;
+            dcs_list = dcs;
+            pthread_mutex_init(&dcs->cs, &_criticals_attr);
+        }
+        pthread_mutex_unlock(&critical_section.cs);
+    }
+    pthread_mutex_lock(&dcs->cs);
+}
+
+void _d_criticalexit(D_CRITICAL_SECTION *dcs)
+{
+    //printf("_d_criticalexit(dcs = x%x)\n", dcs);
+    pthread_mutex_unlock(&dcs->cs);
+}
+
+void _STI_critical_init()
+{
+    if (!dcs_list)
+    {   //printf("_STI_critical_init()\n");
+        pthread_mutexattr_init(&_criticals_attr);
+        pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE);
+
+        // The global critical section doesn't need to be recursive
+        pthread_mutex_init(&critical_section.cs, 0);
+        dcs_list = &critical_section;
+    }
+}
+
+void _STD_critical_term()
+{
+    if (dcs_list)
+    {   //printf("_STI_critical_term()\n");
+        while (dcs_list)
+        {
+            //printf("\tlooping... %x\n", dcs_list);
+            pthread_mutex_destroy(&dcs_list->cs);
+            dcs_list = dcs_list->next;
+        }
+    }
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/deh.c	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,724 @@
+/**
+ * Implementation of exception handling support routines for Windows.
+ *
+ * Copyright: Copyright Digital Mars 1999 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 1999 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#include        <stdio.h>
+#include        <string.h>
+#include        <assert.h>
+#include        <stdlib.h>
+
+/* ======================== Win32 =============================== */
+
+#if _WIN32
+
+#include        <excpt.h>
+#include        <windows.h>
+
+//#include      "\sc\src\include\ehsup.h"
+
+/*** From Digital Mars C runtime library ***/
+EXCEPTION_DISPOSITION __cdecl _local_except_handler (EXCEPTION_RECORD *ExceptionRecord,
+    void* EstablisherFrame,
+        void *ContextRecord,
+        void *DispatcherContext
+        );
+void __cdecl _global_unwind(void *frame,EXCEPTION_RECORD *eRecord);
+#define EXCEPTION_UNWIND  6  // Flag to indicate if the system is unwinding
+
+extern DWORD _except_list;
+/*** ***/
+
+#include        "mars.h"
+
+extern ClassInfo D6object9Throwable7__ClassZ;
+#define _Class_9Throwable D6object9Throwable7__ClassZ;
+
+extern ClassInfo D6object5Error7__ClassZ;
+#define _Class_5Error D6object5Error7__ClassZ
+
+typedef int (__pascal *fp_t)();   // function pointer in ambient memory model
+
+// The layout of DEstablisherFrame is the same for C++
+
+struct DEstablisherFrame
+{
+    void *prev;                 // pointer to previous exception list
+    void *handler;              // pointer to routine for exception handler
+    DWORD table_index;          // current index into handler_info[]
+    DWORD ebp;                  // this is EBP of routine
+};
+
+struct DHandlerInfo
+{
+    int prev_index;             // previous table index
+    unsigned cioffset;          // offset to DCatchInfo data from start of table (!=0 if try-catch)
+    void *finally_code;         // pointer to finally code to execute
+                                // (!=0 if try-finally)
+};
+
+// Address of DHandlerTable is passed in EAX to _d_framehandler()
+
+struct DHandlerTable
+{
+    void *fptr;                 // pointer to start of function
+    unsigned espoffset;         // offset of ESP from EBP
+    unsigned retoffset;         // offset from start of function to return code
+    struct DHandlerInfo handler_info[1];
+};
+
+struct DCatchBlock
+{
+    ClassInfo *type;            // catch type
+    unsigned bpoffset;          // EBP offset of catch var
+    void *code;                 // catch handler code
+};
+
+// Create one of these for each try-catch
+struct DCatchInfo
+{
+    unsigned ncatches;                  // number of catch blocks
+    struct DCatchBlock catch_block[1];  // data for each catch block
+};
+
+// Macro to make our own exception code
+#define MAKE_EXCEPTION_CODE(severity, facility, exception)      \
+        (((severity) << 30) | (1 << 29) | (0 << 28) | ((facility) << 16) | (exception))
+
+#define STATUS_DIGITAL_MARS_D_EXCEPTION         MAKE_EXCEPTION_CODE(3,'D',1)
+
+Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record);
+void __cdecl _d_local_unwind(struct DHandlerTable *handler_table, struct DEstablisherFrame *frame, int stop_index);
+
+
+/***********************************
+ * The frame handler, this is called for each frame that has been registered
+ * in the OS except_list.
+ * Input:
+ *      EAX     the handler table for the frame
+ */
+
+EXCEPTION_DISPOSITION _d_framehandler(
+            EXCEPTION_RECORD *exception_record,
+            struct DEstablisherFrame *frame,
+            CONTEXT context,
+            void *dispatcher_context)
+{
+    struct DHandlerTable *handler_table;
+
+    __asm { mov handler_table,EAX }
+
+    if (exception_record->ExceptionFlags & EXCEPTION_UNWIND)
+    {
+         // Call all the finally blocks in this frame
+         _d_local_unwind(handler_table, frame, -1);
+    }
+    else
+    {
+        // Jump to catch block if matching one is found
+
+        int ndx,prev_ndx,i;
+        struct DHandlerInfo *phi;
+        struct DCatchInfo *pci;
+        struct DCatchBlock *pcb;
+        unsigned ncatches;              // number of catches in the current handler
+        Object *pti;
+        ClassInfo *ci;
+
+        ci = NULL;                      // only compute it if we need it
+
+        // walk through handler table, checking each handler
+        // with an index smaller than the current table_index
+        for (ndx = frame->table_index; ndx != -1; ndx = prev_ndx)
+        {
+            phi = &handler_table->handler_info[ndx];
+            prev_ndx = phi->prev_index;
+            if (phi->cioffset)
+            {
+                // this is a catch handler (no finally)
+                pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset);
+                ncatches = pci->ncatches;
+                for (i = 0; i < ncatches; i++)
+                {
+                    pcb = &pci->catch_block[i];
+
+                    if (!ci)
+                    {
+                        // This code must match the translation code
+                        if (exception_record->ExceptionCode == STATUS_DIGITAL_MARS_D_EXCEPTION)
+                        {
+                            //printf("ei[0] = %p\n", exception_record->ExceptionInformation[0]);
+                            ci = **(ClassInfo ***)(exception_record->ExceptionInformation[0]);
+                        }
+                        else
+                            ci = &_Class_9Throwable;
+                    }
+
+                    if (_d_isbaseof(ci, pcb->type))
+                    {
+                        // Matched the catch type, so we've found the handler.
+                        int regebp;
+
+                        pti = _d_translate_se_to_d_exception(exception_record);
+
+                        // Initialize catch variable
+                        regebp = (int)&frame->ebp;              // EBP for this frame
+                        *(void **)(regebp + (pcb->bpoffset)) = pti;
+
+                        // Have system call all finally blocks in intervening frames
+                        _global_unwind(frame, exception_record);
+
+                        // Call all the finally blocks skipped in this frame
+                        _d_local_unwind(handler_table, frame, ndx);
+
+                        frame->table_index = prev_ndx;  // we are out of this handler
+
+                        // Jump to catch block. Does not return.
+                        {
+                            unsigned catch_esp;
+                            fp_t catch_addr;
+
+                            catch_addr = (fp_t)(pcb->code);
+                            catch_esp = regebp - handler_table->espoffset - sizeof(fp_t);
+                            _asm
+                            {
+                                mov     EAX,catch_esp
+                                mov     ECX,catch_addr
+                                mov     [EAX],ECX
+                                mov     EBP,regebp
+                                mov     ESP,EAX         // reset stack
+                                ret                     // jump to catch block
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return ExceptionContinueSearch;
+}
+
+/***********************************
+ * Exception filter for use in __try..__except block
+ * surrounding call to Dmain()
+ */
+
+int _d_exception_filter(struct _EXCEPTION_POINTERS *eptrs,
+                        int retval,
+                        Object **exception_object)
+{
+    *exception_object = _d_translate_se_to_d_exception(eptrs->ExceptionRecord);
+    return retval;
+}
+
+/***********************************
+ * Throw a D object.
+ */
+
+void __stdcall _d_throw(Object *h)
+{
+    //printf("_d_throw(h = %p, &h = %p)\n", h, &h);
+    //printf("\tvptr = %p\n", *(void **)h);
+    RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION,
+                   EXCEPTION_NONCONTINUABLE,
+                   1, (DWORD *)&h);
+}
+
+/***********************************
+ * Create an exception object
+ */
+
+Object *_d_create_exception_object(ClassInfo *ci, char *msg)
+{
+    Throwable *exc;
+
+    exc = (Throwable *)_d_newclass(ci);
+    // BUG: what if _d_newclass() throws an out of memory exception?
+
+    if (msg)
+    {
+        exc->msglen = strlen(msg);
+        exc->msg = msg;
+    }
+    return (Object *)exc;
+}
+
+/***********************************
+ * Converts a Windows Structured Exception code to a D Exception Object.
+ */
+
+Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record)
+{
+    Object *pti;
+
+    switch (exception_record->ExceptionCode) {
+        case STATUS_DIGITAL_MARS_D_EXCEPTION:
+            // Generated D exception
+            pti = (Object *)(exception_record->ExceptionInformation[0]);
+            break;
+
+        case STATUS_INTEGER_DIVIDE_BY_ZERO:
+            pti = _d_create_exception_object(&_Class_5Error, "Integer Divide by Zero");
+            break;
+
+        case STATUS_FLOAT_DIVIDE_BY_ZERO:
+            pti = _d_create_exception_object(&_Class_5Error, "Float Divide by Zero");
+            break;
+
+        case STATUS_ACCESS_VIOLATION:
+            pti = _d_create_exception_object(&_Class_5Error, "Access Violation");
+            break;
+
+        case STATUS_STACK_OVERFLOW:
+            pti = _d_create_exception_object(&_Class_5Error, "Stack Overflow");
+            break;
+
+        case STATUS_DATATYPE_MISALIGNMENT:
+            pti = _d_create_exception_object(&_Class_5Error, "Datatype Misalignment");
+            break;
+
+        case STATUS_ARRAY_BOUNDS_EXCEEDED:
+            pti = _d_create_exception_object(&_Class_5Error, "Array Bounds Exceeded");
+            break;
+
+        case STATUS_FLOAT_INVALID_OPERATION:
+            pti = _d_create_exception_object(&_Class_5Error, "Invalid Floating Point Operation");
+            break;
+
+        case STATUS_FLOAT_DENORMAL_OPERAND:
+            pti = _d_create_exception_object(&_Class_5Error, "Floating Point Denormal Operand");
+            break;
+
+        case STATUS_FLOAT_INEXACT_RESULT:
+            pti = _d_create_exception_object(&_Class_5Error, "Floating Point Inexact Result");
+            break;
+
+        case STATUS_FLOAT_OVERFLOW:
+            pti = _d_create_exception_object(&_Class_5Error, "Floating Point Overflow");
+            break;
+
+        case STATUS_FLOAT_UNDERFLOW:
+            pti = _d_create_exception_object(&_Class_5Error, "Floating Point Underflow");
+            break;
+
+        case STATUS_FLOAT_STACK_CHECK:
+            pti = _d_create_exception_object(&_Class_5Error, "Floating Point Stack Check");
+            break;
+
+        case STATUS_PRIVILEGED_INSTRUCTION:
+            pti = _d_create_exception_object(&_Class_5Error, "Privileged Instruction");
+            break;
+
+        case STATUS_ILLEGAL_INSTRUCTION:
+            pti = _d_create_exception_object(&_Class_5Error, "Illegal Instruction");
+            break;
+
+        case STATUS_BREAKPOINT:
+            pti = _d_create_exception_object(&_Class_5Error, "Breakpoint");
+            break;
+
+        case STATUS_IN_PAGE_ERROR:
+            pti = _d_create_exception_object(&_Class_5Error, "Win32 In Page Exception");
+            break;
+/*
+        case STATUS_INTEGER_OVERFLOW: // not supported on any x86 processor
+        case STATUS_INVALID_DISPOSITION:
+        case STATUS_NONCONTINUABLE_EXCEPTION:
+        case STATUS_SINGLE_STEP:
+		case DBG_CONTROL_C: // only when a debugger is attached
+        // In DMC, but not in Microsoft docs
+        case STATUS_GUARD_PAGE_VIOLATION:
+        case STATUS_INVALID_HANDLE:
+*/
+        // convert all other exception codes into a Win32Exception
+        default:
+            pti = _d_create_exception_object(&_Class_5Error, "Win32 Exception");
+            break;
+    }
+
+    return pti;
+}
+
+/**************************************
+ * Call finally blocks in the current stack frame until stop_index.
+ * This is roughly equivalent to _local_unwind() for C in \src\win32\ehsup.c
+ */
+
+void __cdecl _d_local_unwind(struct DHandlerTable *handler_table,
+        struct DEstablisherFrame *frame, int stop_index)
+{
+    struct DHandlerInfo *phi;
+    struct DCatchInfo *pci;
+    int i;
+
+    // Set up a special exception handler to catch double-fault exceptions.
+    __asm
+    {
+        push    dword ptr -1
+        push    dword ptr 0
+        push    offset _local_except_handler    // defined in src\win32\ehsup.c
+        push    dword ptr fs:_except_list
+        mov     FS:_except_list,ESP
+    }
+
+    for (i = frame->table_index; i != -1 && i != stop_index; i = phi->prev_index)
+    {
+        phi = &handler_table->handler_info[i];
+        if (phi->finally_code)
+        {
+            // Note that it is unnecessary to adjust the ESP, as the finally block
+            // accesses all items on the stack as relative to EBP.
+
+            DWORD *catch_ebp = &frame->ebp;
+            void *blockaddr = phi->finally_code;
+
+            _asm
+            {
+                push    EBX
+                mov     EBX,blockaddr
+                push    EBP
+                mov     EBP,catch_ebp
+                call    EBX
+                pop     EBP
+                pop     EBX
+            }
+        }
+    }
+
+    _asm
+    {
+        pop     FS:_except_list
+        add     ESP,12
+    }
+}
+
+/***********************************
+ * external version of the unwinder
+ */
+
+__declspec(naked) void __cdecl _d_local_unwind2()
+{
+    __asm
+    {
+        jmp     _d_local_unwind
+    }
+}
+
+/***********************************
+ * The frame handler, this is called for each frame that has been registered
+ * in the OS except_list.
+ * Input:
+ *      EAX     the handler table for the frame
+ */
+
+EXCEPTION_DISPOSITION _d_monitor_handler(
+            EXCEPTION_RECORD *exception_record,
+            struct DEstablisherFrame *frame,
+            CONTEXT context,
+            void *dispatcher_context)
+{
+    if (exception_record->ExceptionFlags & EXCEPTION_UNWIND)
+    {
+        _d_monitorexit((Object *)frame->table_index);
+    }
+    else
+    {
+    }
+    return ExceptionContinueSearch;
+}
+
+/***********************************
+ */
+
+void _d_monitor_prolog(void *x, void *y, Object *h)
+{
+    __asm
+    {
+        push    EAX
+    }
+    //printf("_d_monitor_prolog(x=%p, y=%p, h=%p)\n", x, y, h);
+    _d_monitorenter(h);
+    __asm
+    {
+        pop     EAX
+    }
+}
+
+/***********************************
+ */
+
+void _d_monitor_epilog(void *x, void *y, Object *h)
+{
+    //printf("_d_monitor_epilog(x=%p, y=%p, h=%p)\n", x, y, h);
+    __asm
+    {
+        push    EAX
+        push    EDX
+    }
+    _d_monitorexit(h);
+    __asm
+    {
+        pop     EDX
+        pop     EAX
+    }
+}
+
+#endif
+
+/* ======================== linux =============================== */
+
+#if linux
+
+#include        "mars.h"
+
+extern ClassInfo D6object9Throwable7__ClassZ;
+#define _Class_9Throwable D6object9Throwable7__ClassZ;
+
+extern ClassInfo D6object5Error7__ClassZ;
+#define _Class_5Error D6object5Error7__ClassZ
+
+typedef int (*fp_t)();   // function pointer in ambient memory model
+
+struct DHandlerInfo
+{
+    unsigned offset;            // offset from function address to start of guarded section
+    int prev_index;             // previous table index
+    unsigned cioffset;          // offset to DCatchInfo data from start of table (!=0 if try-catch)
+    void *finally_code;         // pointer to finally code to execute
+                                // (!=0 if try-finally)
+};
+
+// Address of DHandlerTable, searched for by eh_finddata()
+
+struct DHandlerTable
+{
+    void *fptr;                 // pointer to start of function
+    unsigned espoffset;         // offset of ESP from EBP
+    unsigned retoffset;         // offset from start of function to return code
+    unsigned nhandlers;         // dimension of handler_info[]
+    struct DHandlerInfo handler_info[1];
+};
+
+struct DCatchBlock
+{
+    ClassInfo *type;            // catch type
+    unsigned bpoffset;          // EBP offset of catch var
+    void *code;                 // catch handler code
+};
+
+// Create one of these for each try-catch
+struct DCatchInfo
+{
+    unsigned ncatches;                  // number of catch blocks
+    struct DCatchBlock catch_block[1];  // data for each catch block
+};
+
+// One of these is generated for each function with try-catch or try-finally
+
+struct FuncTable
+{
+    void *fptr;                 // pointer to start of function
+    struct DHandlerTable *handlertable; // eh data for this function
+    unsigned size;              // size of function in bytes
+};
+
+extern struct FuncTable *table_start;
+extern struct FuncTable *table_end;
+
+void terminate()
+{
+//    _asm
+//    {
+//      hlt
+//    }
+}
+
+/*******************************************
+ * Given address that is inside a function,
+ * figure out which function it is in.
+ * Return DHandlerTable if there is one, NULL if not.
+ */
+
+struct DHandlerTable *__eh_finddata(void *address)
+{
+    struct FuncTable *ft;
+
+    for (ft = (struct FuncTable *)table_start;
+         ft < (struct FuncTable *)table_end;
+         ft++)
+    {
+        if (ft->fptr <= address &&
+            address < (void *)((char *)ft->fptr + ft->size))
+        {
+            return ft->handlertable;
+        }
+    }
+    return NULL;
+}
+
+
+/******************************
+ * Given EBP, find return address to caller, and caller's EBP.
+ * Input:
+ *   regbp       Value of EBP for current function
+ *   *pretaddr   Return address
+ * Output:
+ *   *pretaddr   return address to caller
+ * Returns:
+ *   caller's EBP
+ */
+
+unsigned __eh_find_caller(unsigned regbp, unsigned *pretaddr)
+{
+    unsigned bp = *(unsigned *)regbp;
+
+    if (bp)         // if not end of call chain
+    {
+        // Perform sanity checks on new EBP.
+        // If it is screwed up, terminate() hopefully before we do more damage.
+        if (bp <= regbp)
+            // stack should grow to smaller values
+            terminate();
+
+        *pretaddr = *(unsigned *)(regbp + sizeof(int));
+    }
+    return bp;
+}
+
+/***********************************
+ * Throw a D object.
+ */
+
+void __stdcall _d_throw(Object *h)
+{
+    unsigned regebp;
+
+    //printf("_d_throw(h = %p, &h = %p)\n", h, &h);
+    //printf("\tvptr = %p\n", *(void **)h);
+
+    regebp = _EBP;
+
+    while (1)           // for each function on the stack
+    {
+        struct DHandlerTable *handler_table;
+        struct FuncTable *pfunc;
+        struct DHandlerInfo *phi;
+        unsigned retaddr;
+        unsigned funcoffset;
+        unsigned spoff;
+        unsigned retoffset;
+        int index;
+        int dim;
+        int ndx;
+        int prev_ndx;
+
+        regebp = __eh_find_caller(regebp,&retaddr);
+        if (!regebp)
+            // if end of call chain
+            break;
+
+        handler_table = __eh_finddata((void *)retaddr);   // find static data associated with function
+        if (!handler_table)         // if no static data
+        {
+            continue;
+        }
+        funcoffset = (unsigned)handler_table->fptr;
+        spoff = handler_table->espoffset;
+        retoffset = handler_table->retoffset;
+
+#ifdef DEBUG
+        printf("retaddr = x%x\n",(unsigned)retaddr);
+        printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n",
+        regebp,funcoffset,spoff,retoffset);
+#endif
+
+        // Find start index for retaddr in static data
+        dim = handler_table->nhandlers;
+        index = -1;
+        for (int i = 0; i < dim; i++)
+        {
+            phi = &handler_table->handler_info[i];
+
+            if ((unsigned)retaddr >= funcoffset + phi->offset)
+                index = i;
+        }
+
+        // walk through handler table, checking each handler
+        // with an index smaller than the current table_index
+        for (ndx = index; ndx != -1; ndx = prev_ndx)
+        {
+            phi = &handler_table->handler_info[ndx];
+            prev_ndx = phi->prev_index;
+            if (phi->cioffset)
+            {
+                // this is a catch handler (no finally)
+                struct DCatchInfo *pci;
+                int ncatches;
+                int i;
+
+                pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset);
+                ncatches = pci->ncatches;
+                for (i = 0; i < ncatches; i++)
+                {
+                    struct DCatchBlock *pcb;
+                    ClassInfo *ci = **(ClassInfo ***)h;
+
+                    pcb = &pci->catch_block[i];
+
+                    if (_d_isbaseof(ci, pcb->type))
+                    {   // Matched the catch type, so we've found the handler.
+
+                        // Initialize catch variable
+                        *(void **)(regebp + (pcb->bpoffset)) = h;
+
+                        // Jump to catch block. Does not return.
+                        {
+                            unsigned catch_esp;
+                            fp_t catch_addr;
+
+                            catch_addr = (fp_t)(pcb->code);
+                            catch_esp = regebp - handler_table->espoffset - sizeof(fp_t);
+                            _asm
+                            {
+                                mov     EAX,catch_esp
+                                mov     ECX,catch_addr
+                                mov     [EAX],ECX
+                                mov     EBP,regebp
+                                mov     ESP,EAX         // reset stack
+                                ret                     // jump to catch block
+                            }
+                        }
+                    }
+                }
+            }
+            else if (phi->finally_code)
+            {   // Call finally block
+                // Note that it is unnecessary to adjust the ESP, as the finally block
+                // accesses all items on the stack as relative to EBP.
+
+                void *blockaddr = phi->finally_code;
+
+                _asm
+                {
+                    push        EBX
+                    mov         EBX,blockaddr
+                    push        EBP
+                    mov         EBP,regebp
+                    call        EBX
+                    pop         EBP
+                    pop         EBX
+                }
+            }
+        }
+    }
+}
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/deh2.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,316 @@
+/**
+ * Implementation of exception handling support routines for Posix.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.deh2;
+
+//debug=1;
+
+extern (C)
+{
+    extern __gshared
+    {
+	void* _deh_beg;
+	void* _deh_end;
+    }
+
+    int _d_isbaseof(ClassInfo oc, ClassInfo c);
+}
+
+alias int (*fp_t)();   // function pointer in ambient memory model
+
+struct DHandlerInfo
+{
+    uint offset;                // offset from function address to start of guarded section
+    uint endoffset;             // offset of end of guarded section
+    int prev_index;             // previous table index
+    uint cioffset;              // offset to DCatchInfo data from start of table (!=0 if try-catch)
+    void *finally_code;         // pointer to finally code to execute
+                                // (!=0 if try-finally)
+}
+
+// Address of DHandlerTable, searched for by eh_finddata()
+
+struct DHandlerTable
+{
+    void *fptr;                 // pointer to start of function
+    uint espoffset;             // offset of ESP from EBP
+    uint retoffset;             // offset from start of function to return code
+    uint nhandlers;             // dimension of handler_info[]
+    DHandlerInfo handler_info[1];
+}
+
+struct DCatchBlock
+{
+    ClassInfo type;             // catch type
+    uint bpoffset;              // EBP offset of catch var
+    void *code;                 // catch handler code
+}
+
+// Create one of these for each try-catch
+struct DCatchInfo
+{
+    uint ncatches;                      // number of catch blocks
+    DCatchBlock catch_block[1];         // data for each catch block
+}
+
+// One of these is generated for each function with try-catch or try-finally
+
+struct FuncTable
+{
+    void *fptr;                 // pointer to start of function
+    DHandlerTable *handlertable; // eh data for this function
+    uint fsize;         // size of function in bytes
+}
+
+void terminate()
+{
+    asm
+    {
+        hlt ;
+    }
+}
+
+/*******************************************
+ * Given address that is inside a function,
+ * figure out which function it is in.
+ * Return DHandlerTable if there is one, NULL if not.
+ */
+
+DHandlerTable *__eh_finddata(void *address)
+{
+    FuncTable *ft;
+
+//    debug printf("__eh_finddata(address = x%x)\n", address);
+//    debug printf("_deh_beg = x%x, _deh_end = x%x\n", &_deh_beg, &_deh_end);
+    for (ft = cast(FuncTable *)&_deh_beg;
+         ft < cast(FuncTable *)&_deh_end;
+         ft++)
+    {
+//      debug printf("\tfptr = x%x, fsize = x%03x, handlertable = x%x\n",
+//              ft.fptr, ft.fsize, ft.handlertable);
+
+        if (ft.fptr <= address &&
+            address < cast(void *)(cast(char *)ft.fptr + ft.fsize))
+        {
+//          debug printf("\tfound handler table\n");
+            return ft.handlertable;
+        }
+    }
+//    debug printf("\tnot found\n");
+    return null;
+}
+
+
+/******************************
+ * Given EBP, find return address to caller, and caller's EBP.
+ * Input:
+ *   regbp       Value of EBP for current function
+ *   *pretaddr   Return address
+ * Output:
+ *   *pretaddr   return address to caller
+ * Returns:
+ *   caller's EBP
+ */
+
+uint __eh_find_caller(uint regbp, uint *pretaddr)
+{
+    uint bp = *cast(uint *)regbp;
+
+    if (bp)         // if not end of call chain
+    {
+        // Perform sanity checks on new EBP.
+        // If it is screwed up, terminate() hopefully before we do more damage.
+        if (bp <= regbp)
+            // stack should grow to smaller values
+            terminate();
+
+        *pretaddr = *cast(uint *)(regbp + int.sizeof);
+    }
+    return bp;
+}
+
+/***********************************
+ * Throw a D object.
+ */
+
+extern (Windows) void _d_throw(Object *h)
+{
+    uint regebp;
+
+    debug
+    {
+        printf("_d_throw(h = %p, &h = %p)\n", h, &h);
+        printf("\tvptr = %p\n", *cast(void **)h);
+    }
+
+    asm
+    {
+        mov regebp,EBP  ;
+    }
+
+//static uint abc;
+//if (++abc == 2) *(char *)0=0;
+
+//int count = 0;
+    while (1)           // for each function on the stack
+    {
+        DHandlerTable *handler_table;
+        FuncTable *pfunc;
+        DHandlerInfo *phi;
+        uint retaddr;
+        uint funcoffset;
+        uint spoff;
+        uint retoffset;
+        int index;
+        int dim;
+        int ndx;
+        int prev_ndx;
+
+        regebp = __eh_find_caller(regebp,&retaddr);
+        if (!regebp)
+        {   // if end of call chain
+            debug printf("end of call chain\n");
+            break;
+        }
+
+        debug printf("found caller, EBP = x%x, retaddr = x%x\n", regebp, retaddr);
+//if (++count == 12) *(char*)0=0;
+        handler_table = __eh_finddata(cast(void *)retaddr);   // find static data associated with function
+        if (!handler_table)         // if no static data
+        {
+            debug printf("no handler table\n");
+            continue;
+        }
+        funcoffset = cast(uint)handler_table.fptr;
+        spoff = handler_table.espoffset;
+        retoffset = handler_table.retoffset;
+
+        debug
+        {
+            printf("retaddr = x%x\n",cast(uint)retaddr);
+            printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n",
+            regebp,funcoffset,spoff,retoffset);
+        }
+
+        // Find start index for retaddr in static data
+        dim = handler_table.nhandlers;
+
+        debug
+        {
+            printf("handler_info[]:\n");
+            for (int i = 0; i < dim; i++)
+            {
+                phi = &handler_table.handler_info[i];
+                printf("\t[%d]: offset = x%04x, endoffset = x%04x, prev_index = %d, cioffset = x%04x, finally_code = %x\n",
+                        i, phi.offset, phi.endoffset, phi.prev_index, phi.cioffset, phi.finally_code);
+            }
+        }
+
+        index = -1;
+        for (int i = 0; i < dim; i++)
+        {
+            phi = &handler_table.handler_info[i];
+
+            debug printf("i = %d, phi.offset = %04x\n", i, funcoffset + phi.offset);
+            if (cast(uint)retaddr > funcoffset + phi.offset &&
+                cast(uint)retaddr <= funcoffset + phi.endoffset)
+                index = i;
+        }
+        debug printf("index = %d\n", index);
+
+        // walk through handler table, checking each handler
+        // with an index smaller than the current table_index
+        for (ndx = index; ndx != -1; ndx = prev_ndx)
+        {
+            phi = &handler_table.handler_info[ndx];
+            prev_ndx = phi.prev_index;
+            if (phi.cioffset)
+            {
+                // this is a catch handler (no finally)
+                DCatchInfo *pci;
+                int ncatches;
+                int i;
+
+                pci = cast(DCatchInfo *)(cast(char *)handler_table + phi.cioffset);
+                ncatches = pci.ncatches;
+                for (i = 0; i < ncatches; i++)
+                {
+                    DCatchBlock *pcb;
+                    ClassInfo ci = **cast(ClassInfo **)h;
+
+                    pcb = &pci.catch_block[i];
+
+                    if (_d_isbaseof(ci, pcb.type))
+                    {   // Matched the catch type, so we've found the handler.
+
+                        // Initialize catch variable
+                        *cast(void **)(regebp + (pcb.bpoffset)) = h;
+
+                        // Jump to catch block. Does not return.
+                        {
+                            uint catch_esp;
+                            fp_t catch_addr;
+
+                            catch_addr = cast(fp_t)(pcb.code);
+                            catch_esp = regebp - handler_table.espoffset - fp_t.sizeof;
+                            asm
+                            {
+                                mov     EAX,catch_esp   ;
+                                mov     ECX,catch_addr  ;
+                                mov     [EAX],ECX       ;
+                                mov     EBP,regebp      ;
+                                mov     ESP,EAX         ; // reset stack
+                                ret                     ; // jump to catch block
+                            }
+                        }
+                    }
+                }
+            }
+            else if (phi.finally_code)
+            {   // Call finally block
+                // Note that it is unnecessary to adjust the ESP, as the finally block
+                // accesses all items on the stack as relative to EBP.
+
+                void *blockaddr = phi.finally_code;
+
+                version (OSX)
+                {
+                    asm
+                    {
+                        sub     ESP,4           ; // align stack to 16
+                        push    EBX             ;
+                        mov     EBX,blockaddr   ;
+                        push    EBP             ;
+                        mov     EBP,regebp      ;
+                        call    EBX             ;
+                        pop     EBP             ;
+                        pop     EBX             ;
+                        add     ESP,4           ;
+                    }
+                }
+                else
+                {
+                    asm
+                    {
+                        push        EBX             ;
+                        mov         EBX,blockaddr   ;
+                        push        EBP             ;
+                        mov         EBP,regebp      ;
+                        call        EBX             ;
+                        pop         EBP             ;
+                        pop         EBX             ;
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/dmain2.BAK	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,374 @@
+/*
+ * Placed into the Public Domain.
+ * written by Walter Bright
+ * www.digitalmars.com
+ */
+
+/*
+ *  Modified by Sean Kelly for use with the D Runtime Project
+ */
+
+module rt.dmain2;
+
+private
+{
+    import memory;
+    import util.console;
+    import core.stdc.stddef;
+    import core.stdc.stdlib;
+    import core.stdc.string;
+}
+
+version (Windows)
+{
+    extern (Windows) alias int function() FARPROC;
+    extern (Windows) FARPROC    GetProcAddress(void*, in char*);
+    extern (Windows) void*      LoadLibraryA(in char*);
+    extern (Windows) int        FreeLibrary(void*);
+    extern (Windows) void*      LocalFree(void*);
+    extern (Windows) wchar_t*   GetCommandLineW();
+    extern (Windows) wchar_t**  CommandLineToArgvW(wchar_t*, int*);
+    extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
+    pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW
+}
+
+extern (C) void _STI_monitor_staticctor();
+extern (C) void _STD_monitor_staticdtor();
+extern (C) void _STI_critical_init();
+extern (C) void _STD_critical_term();
+extern (C) void gc_init();
+extern (C) void gc_term();
+extern (C) void _minit();
+extern (C) void _moduleCtor();
+extern (C) void _moduleDtor();
+extern (C) void thread_joinAll();
+
+/***********************************
+ * These are a temporary means of providing a GC hook for DLL use.  They may be
+ * replaced with some other similar functionality later.
+ */
+extern (C)
+{
+    void* gc_getProxy();
+    void  gc_setProxy(void* p);
+    void  gc_clrProxy();
+
+    alias void* function()      gcGetFn;
+    alias void  function(void*) gcSetFn;
+    alias void  function()      gcClrFn;
+}
+
+extern (C) void* rt_loadLibrary(in char[] name)
+{
+    version (Windows)
+    {
+        char[260] temp = void;
+        temp[0 .. name.length] = name[];
+        temp[name.length] = cast(char) 0;
+        void* ptr = LoadLibraryA(temp.ptr);
+        if (ptr is null)
+            return ptr;
+        gcSetFn gcSet = cast(gcSetFn) GetProcAddress(ptr, "gc_setProxy");
+        if (gcSet !is null)
+            gcSet(gc_getProxy());
+        return ptr;
+
+    }
+    else version (linux)
+    {
+        throw new Exception("rt_loadLibrary not yet implemented on linux.");
+    }
+}
+
+extern (C) bool rt_unloadLibrary(void* ptr)
+{
+    version (Windows)
+    {
+        gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy");
+        if (gcClr !is null)
+            gcClr();
+        return FreeLibrary(ptr) != 0;
+    }
+    else version (linux)
+    {
+        throw new Exception("rt_unloadLibrary not yet implemented on linux.");
+    }
+}
+
+/***********************************
+ * These functions must be defined for any D program linked
+ * against this library.
+ */
+extern (C) void onAssertError(string file, size_t line);
+extern (C) void onAssertErrorMsg(string file, size_t line, string msg);
+extern (C) void onRangeError(string file, size_t line);
+extern (C) void onHiddenFuncError(Object o);
+extern (C) void onSwitchError(string file, size_t line);
+extern (C) bool runModuleUnitTests();
+
+// this function is called from the utf module
+//extern (C) void onUnicodeError(string msg, size_t idx);
+
+/***********************************
+ * These are internal callbacks for various language errors.
+ */
+extern (C) void _d_assert(string file, uint line)
+{
+    onAssertError(file, line);
+}
+
+extern (C) static void _d_assert_msg(string msg, string file, uint line)
+{
+    onAssertErrorMsg(file, line, msg);
+}
+
+extern (C) void _d_array_bounds(string file, uint line)
+{
+    onRangeError(file, line);
+}
+
+extern (C) void _d_switch_error(string file, uint line)
+{
+    onSwitchError(file, line);
+}
+
+extern (C) void _d_hidden_func()
+{
+    Object o;
+    asm
+    {
+        mov o, EAX;
+    }
+    onHiddenFuncError(o);
+}
+
+bool _d_isHalting = false;
+
+extern (C) bool rt_isHalting()
+{
+    return _d_isHalting;
+}
+
+extern (C) bool rt_trapExceptions = true;
+
+void _d_criticalInit()
+{
+    version (linux)
+    {
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+}
+
+alias void delegate(Throwable) ExceptionHandler;
+
+extern (C) bool rt_init(ExceptionHandler dg = null)
+{
+    _d_criticalInit();
+
+    try
+    {
+        gc_init();
+        initStaticDataGC();
+        version (Windows)
+            _minit();
+        _moduleCtor();
+        return true;
+    }
+    catch (Throwable e)
+    {
+        if (dg)
+            dg(e);
+    }
+    catch
+    {
+
+    }
+    _d_criticalTerm();
+    return false;
+}
+
+void _d_criticalTerm()
+{
+    version (linux)
+    {
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+}
+
+extern (C) bool rt_term(ExceptionHandler dg = null)
+{
+    try
+    {
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+        return true;
+    }
+    catch (Throwable e)
+    {
+        if (dg)
+            dg(e);
+    }
+    catch
+    {
+
+    }
+    finally
+    {
+        _d_criticalTerm();
+    }
+    return false;
+}
+
+/***********************************
+ * The D main() function supplied by the user's program
+ */
+int main(char[][] args);
+
+/***********************************
+ * Substitutes for the C main() function.
+ * It's purpose is to wrap the call to the D main()
+ * function and catch any unhandled exceptions.
+ */
+
+extern (C) int main(int argc, char **argv)
+{
+    char[][] args;
+    int result;
+
+    version (linux)
+    {
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+
+    version (Windows)
+    {
+        wchar_t*  wcbuf = GetCommandLineW();
+        size_t    wclen = wcslen(wcbuf);
+        int       wargc = 0;
+        wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
+        assert(wargc == argc);
+
+        char*     cargp = null;
+        size_t    cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
+
+        cargp = cast(char*) alloca(cargl);
+        args  = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
+
+        for (size_t i = 0, p = 0; i < wargc; i++)
+        {
+            int wlen = wcslen(wargs[i]);
+            int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
+            args[i]  = cargp[p .. p+clen];
+            p += clen; assert(p <= cargl);
+            WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
+        }
+        LocalFree(wargs);
+        wargs = null;
+        wargc = 0;
+    }
+    else version (linux)
+    {
+        char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
+        scope(exit) free(am);
+
+        for (size_t i = 0; i < argc; i++)
+        {
+            auto len = strlen(argv[i]);
+            am[i] = argv[i][0 .. len];
+        }
+        args = am[0 .. argc];
+    }
+
+    bool trapExceptions = rt_trapExceptions;
+
+    void tryExec(void delegate() dg)
+    {
+
+        if (trapExceptions)
+        {
+            try
+            {
+                dg();
+            }
+            catch (Throwable e)
+            {
+                while (e)
+                {
+                    if (e.file)
+                    {
+                        // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg);
+                        console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
+                    }
+                    else
+                    {
+                        // fprintf(stderr, "%.*s\n", e.toString());
+                        console (e.toString)("\n");
+                    }
+                    if (e.info)
+                    {
+                        console ("----------------\n");
+                        foreach (t; e.info)
+                            console (t)("\n");
+                    }
+                    if (e.next)
+                        console ("\n");
+                    e = e.next;
+                }
+                result = EXIT_FAILURE;
+            }
+            catch (Object o)
+            {
+                // fprintf(stderr, "%.*s\n", o.toString());
+                console (o.toString)("\n");
+                result = EXIT_FAILURE;
+            }
+        }
+        else
+        {
+            dg();
+        }
+    }
+
+    // NOTE: The lifetime of a process is much like the lifetime of an object:
+    //       it is initialized, then used, then destroyed.  If initialization
+    //       fails, the successive two steps are never reached.  However, if
+    //       initialization succeeds, then cleanup will occur even if the use
+    //       step fails in some way.  Here, the use phase consists of running
+    //       the user's main function.  If main terminates with an exception,
+    //       the exception is handled and then cleanup begins.  An exception
+    //       thrown during cleanup, however, will abort the cleanup process.
+
+    void runMain()
+    {
+        result = main(args);
+    }
+
+    void runAll()
+    {
+        gc_init();
+        initStaticDataGC();
+        version (Windows)
+            _minit();
+        _moduleCtor();
+        if (runModuleUnitTests())
+            tryExec(&runMain);
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+    }
+
+    tryExec(&runAll);
+
+    version (linux)
+    {
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/dmain2.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,394 @@
+/**
+ * Contains main program entry point and support routines.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.dmain2;
+
+private
+{
+    import rt.memory;
+    import rt.util.console;
+    import core.stdc.stddef;
+    import core.stdc.stdlib;
+    import core.stdc.string;
+}
+
+version (Windows)
+{
+    private import core.stdc.wchar_;
+
+    extern (Windows) alias int function() FARPROC;
+    extern (Windows) FARPROC    GetProcAddress(void*, in char*);
+    extern (Windows) void*      LoadLibraryA(in char*);
+    extern (Windows) int        FreeLibrary(void*);
+    extern (Windows) void*      LocalFree(void*);
+    extern (Windows) wchar_t*   GetCommandLineW();
+    extern (Windows) wchar_t**  CommandLineToArgvW(wchar_t*, int*);
+    extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
+    pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW
+}
+
+extern (C) void _STI_monitor_staticctor();
+extern (C) void _STD_monitor_staticdtor();
+extern (C) void _STI_critical_init();
+extern (C) void _STD_critical_term();
+extern (C) void gc_init();
+extern (C) void gc_term();
+extern (C) void _minit();
+extern (C) void _moduleCtor();
+extern (C) void _moduleDtor();
+extern (C) void thread_joinAll();
+
+version (OSX)
+{
+    // The bottom of the stack
+    extern (C) void* __osx_stack_end = cast(void*)0xC0000000;
+}
+
+/***********************************
+ * These are a temporary means of providing a GC hook for DLL use.  They may be
+ * replaced with some other similar functionality later.
+ */
+extern (C)
+{
+    void* gc_getProxy();
+    void  gc_setProxy(void* p);
+    void  gc_clrProxy();
+
+    alias void* function()      gcGetFn;
+    alias void  function(void*) gcSetFn;
+    alias void  function()      gcClrFn;
+}
+
+extern (C) void* rt_loadLibrary(in char[] name)
+{
+    version (Windows)
+    {
+        char[260] temp = void;
+        temp[0 .. name.length] = name[];
+        temp[name.length] = cast(char) 0;
+        void* ptr = LoadLibraryA(temp.ptr);
+        if (ptr is null)
+            return ptr;
+        gcSetFn gcSet = cast(gcSetFn) GetProcAddress(ptr, "gc_setProxy");
+        if (gcSet !is null)
+            gcSet(gc_getProxy());
+        return ptr;
+
+    }
+    else version (Posix)
+    {
+        throw new Exception("rt_loadLibrary not yet implemented on Posix.");
+    }
+}
+
+extern (C) bool rt_unloadLibrary(void* ptr)
+{
+    version (Windows)
+    {
+        gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy");
+        if (gcClr !is null)
+            gcClr();
+        return FreeLibrary(ptr) != 0;
+    }
+    else version (Posix)
+    {
+        throw new Exception("rt_unloadLibrary not yet implemented on Posix.");
+    }
+}
+
+/***********************************
+ * These functions must be defined for any D program linked
+ * against this library.
+ */
+extern (C) void onAssertError(string file, size_t line);
+extern (C) void onAssertErrorMsg(string file, size_t line, string msg);
+extern (C) void onRangeError(string file, size_t line);
+extern (C) void onHiddenFuncError(Object o);
+extern (C) void onSwitchError(string file, size_t line);
+extern (C) bool runModuleUnitTests();
+
+// this function is called from the utf module
+//extern (C) void onUnicodeError(string msg, size_t idx);
+
+/***********************************
+ * These are internal callbacks for various language errors.
+ */
+extern (C) void _d_assert(string file, uint line)
+{
+    onAssertError(file, line);
+}
+
+extern (C) static void _d_assert_msg(string msg, string file, uint line)
+{
+    onAssertErrorMsg(file, line, msg);
+}
+
+extern (C) void _d_array_bounds(string file, uint line)
+{
+    onRangeError(file, line);
+}
+
+extern (C) void _d_switch_error(string file, uint line)
+{
+    onSwitchError(file, line);
+}
+
+extern (C) void _d_hidden_func()
+{
+    Object o;
+    asm
+    {
+        mov o, EAX;
+    }
+    onHiddenFuncError(o);
+}
+
+shared bool _d_isHalting = false;
+
+extern (C) bool rt_isHalting()
+{
+    return _d_isHalting;
+}
+
+extern (C) shared bool rt_trapExceptions = true;
+
+void _d_criticalInit()
+{
+    version (Posix)
+    {
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+}
+
+alias void delegate(Throwable) ExceptionHandler;
+
+extern (C) bool rt_init(ExceptionHandler dg = null)
+{
+    _d_criticalInit();
+
+    try
+    {
+        gc_init();
+        initStaticDataGC();
+        version (Windows)
+            _minit();
+        _moduleCtor();
+        runModuleUnitTests();
+        return true;
+    }
+    catch (Throwable e)
+    {
+        if (dg)
+            dg(e);
+    }
+    catch
+    {
+
+    }
+    _d_criticalTerm();
+    return false;
+}
+
+void _d_criticalTerm()
+{
+    version (Posix)
+    {
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+}
+
+extern (C) bool rt_term(ExceptionHandler dg = null)
+{
+    try
+    {
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+        return true;
+    }
+    catch (Throwable e)
+    {
+        if (dg)
+            dg(e);
+    }
+    catch
+    {
+
+    }
+    finally
+    {
+        _d_criticalTerm();
+    }
+    return false;
+}
+
+/***********************************
+ * The D main() function supplied by the user's program
+ */
+int main(char[][] args);
+
+/***********************************
+ * Substitutes for the C main() function.
+ * It's purpose is to wrap the call to the D main()
+ * function and catch any unhandled exceptions.
+ */
+
+extern (C) int main(int argc, char **argv)
+{
+    char[][] args;
+    int result;
+
+    version (OSX)
+    {   /* OSX does not provide a way to get at the top of the
+         * stack, except for the magic value 0xC0000000.
+         * But as far as the gc is concerned, argv is at the top
+         * of the main thread's stack, so save the address of that.
+         */
+        __osx_stack_end = cast(void*)&argv;
+    }
+
+    version (Posix)
+    {
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+
+    version (Windows)
+    {
+        wchar_t*  wcbuf = GetCommandLineW();
+        size_t    wclen = wcslen(wcbuf);
+        int       wargc = 0;
+        wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
+        assert(wargc == argc);
+
+        char*     cargp = null;
+        size_t    cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
+
+        cargp = cast(char*) alloca(cargl);
+        args  = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
+
+        for (size_t i = 0, p = 0; i < wargc; i++)
+        {
+            int wlen = wcslen(wargs[i]);
+            int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
+            args[i]  = cargp[p .. p+clen];
+            p += clen; assert(p <= cargl);
+            WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
+        }
+        LocalFree(wargs);
+        wargs = null;
+        wargc = 0;
+    }
+    else version (Posix)
+    {
+        char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
+        scope(exit) free(am);
+
+        for (size_t i = 0; i < argc; i++)
+        {
+            auto len = strlen(argv[i]);
+            am[i] = argv[i][0 .. len];
+        }
+        args = am[0 .. argc];
+    }
+
+    bool trapExceptions = rt_trapExceptions;
+
+    void tryExec(scope void delegate() dg)
+    {
+
+        if (trapExceptions)
+        {
+            try
+            {
+                dg();
+            }
+            catch (Throwable e)
+            {
+                while (e)
+                {
+                    if (e.file)
+                    {
+                        // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg);
+                        console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
+                    }
+                    else
+                    {
+                        // fprintf(stderr, "%.*s\n", e.toString());
+                        console (e.toString)("\n");
+                    }
+                    if (e.info)
+                    {
+                        console ("----------------\n");
+                        foreach (t; e.info)
+                            console (t)("\n");
+                    }
+                    if (e.next)
+                        console ("\n");
+                    e = e.next;
+                }
+                result = EXIT_FAILURE;
+            }
+            catch (Object o)
+            {
+                // fprintf(stderr, "%.*s\n", o.toString());
+                console (o.toString)("\n");
+                result = EXIT_FAILURE;
+            }
+        }
+        else
+        {
+            dg();
+        }
+    }
+
+    // NOTE: The lifetime of a process is much like the lifetime of an object:
+    //       it is initialized, then used, then destroyed.  If initialization
+    //       fails, the successive two steps are never reached.  However, if
+    //       initialization succeeds, then cleanup will occur even if the use
+    //       step fails in some way.  Here, the use phase consists of running
+    //       the user's main function.  If main terminates with an exception,
+    //       the exception is handled and then cleanup begins.  An exception
+    //       thrown during cleanup, however, will abort the cleanup process.
+
+    void runMain()
+    {
+        result = main(args);
+    }
+
+    void runAll()
+    {
+        gc_init();
+        initStaticDataGC();
+        version (Windows)
+            _minit();
+        _moduleCtor();
+        if (runModuleUnitTests())
+            tryExec(&runMain);
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+    }
+
+    tryExec(&runAll);
+
+    version (Posix)
+    {
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/invariant.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,35 @@
+/**
+ * Implementation of invariant support routines.
+ *
+ * Copyright: Copyright Digital Mars 2007 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2007 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+
+/**
+ *
+ */
+void _d_invariant(Object o)
+{   ClassInfo c;
+
+    //printf("__d_invariant(%p)\n", o);
+
+    // BUG: needs to be filename/line of caller, not library routine
+    assert(o !is null); // just do null check, not invariant check
+
+    c = o.classinfo;
+    do
+    {
+        if (c.classInvariant)
+        {
+            (*c.classInvariant)(o);
+        }
+        c = c.base;
+    } while (c);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/invariant_.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,32 @@
+/**
+ * Implementation of invariant support routines.
+ *
+ * Copyright: Copyright Digital Mars 2007 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2007 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.invariant_;
+
+extern (C) void _d_invariant(Object o)
+{   ClassInfo c;
+
+    //printf("__d_invariant(%p)\n", o);
+
+    // BUG: needs to be filename/line of caller, not library routine
+    assert(o !is null); // just do null check, not invariant check
+
+    c = o.classinfo;
+    do
+    {
+        if (c.classInvariant)
+        {
+            (*c.classInvariant)(o);
+        }
+        c = c.base;
+    } while (c);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/lifetime.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,1073 @@
+/**
+ * This module contains all functions related to an object's lifetime:
+ * allocation, resizing, deallocation, and finalization.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.lifetime;
+
+
+private
+{
+    import core.stdc.stdlib;
+    import core.stdc.string;
+    import core.stdc.stdarg;
+    debug(PRINTF) import core.stdc.stdio;
+}
+
+
+private
+{
+    enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001,
+        NO_SCAN  = 0b0000_0010,
+        NO_MOVE  = 0b0000_0100,
+        ALL_BITS = 0b1111_1111
+    }
+
+    struct BlkInfo
+    {
+        void*  base;
+        size_t size;
+        uint   attr;
+    }
+
+    extern (C) uint gc_getAttr( void* p );
+    extern (C) uint gc_setAttr( void* p, uint a );
+    extern (C) uint gc_clrAttr( void* p, uint a );
+
+    extern (C) void*  gc_malloc( size_t sz, uint ba = 0 );
+    extern (C) void*  gc_calloc( size_t sz, uint ba = 0 );
+    extern (C) size_t gc_extend( void* p, size_t mx, size_t sz );
+    extern (C) void   gc_free( void* p );
+
+    extern (C) void*   gc_addrOf( void* p );
+    extern (C) size_t  gc_sizeOf( void* p );
+    extern (C) BlkInfo gc_query( void* p );
+
+    extern (C) void onFinalizeError( ClassInfo c, Throwable e );
+    extern (C) void onOutOfMemoryError();
+
+    extern (C) void _d_monitordelete(Object h, bool det = true);
+
+    enum
+    {
+        PAGESIZE = 4096
+    }
+
+    alias bool function(Object) CollectHandler;
+    __gshared CollectHandler collectHandler = null;
+}
+
+
+/**
+ *
+ */
+extern (C) void* _d_allocmemory(size_t sz)
+{
+    return gc_malloc(sz);
+}
+
+
+/**
+ *
+ */
+extern (C) Object _d_newclass(ClassInfo ci)
+{
+    void* p;
+
+    debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name);
+    if (ci.flags & 1) // if COM object
+    {   /* COM objects are not garbage collected, they are reference counted
+         * using AddRef() and Release().  They get free'd by C's free()
+         * function called by Release() when Release()'s reference count goes
+         * to zero.
+     */
+        p = malloc(ci.init.length);
+        if (!p)
+            onOutOfMemoryError();
+    }
+    else
+    {
+        p = gc_malloc(ci.init.length,
+                      BlkAttr.FINALIZE | (ci.flags & 2 ? BlkAttr.NO_SCAN : 0));
+        debug(PRINTF) printf(" p = %p\n", p);
+    }
+
+    debug(PRINTF)
+    {
+        printf("p = %p\n", p);
+        printf("ci = %p, ci.init = %p, len = %d\n", ci, ci.init, ci.init.length);
+        printf("vptr = %p\n", *cast(void**) ci.init);
+        printf("vtbl[0] = %p\n", (*cast(void***) ci.init)[0]);
+        printf("vtbl[1] = %p\n", (*cast(void***) ci.init)[1]);
+        printf("init[0] = %x\n", (cast(uint*) ci.init)[0]);
+        printf("init[1] = %x\n", (cast(uint*) ci.init)[1]);
+        printf("init[2] = %x\n", (cast(uint*) ci.init)[2]);
+        printf("init[3] = %x\n", (cast(uint*) ci.init)[3]);
+        printf("init[4] = %x\n", (cast(uint*) ci.init)[4]);
+    }
+
+    // initialize it
+    (cast(byte*) p)[0 .. ci.init.length] = ci.init[];
+
+    debug(PRINTF) printf("initialization done\n");
+    return cast(Object) p;
+}
+
+
+/**
+ *
+ */
+extern (C) void _d_delinterface(void** p)
+{
+    if (*p)
+    {
+        Interface* pi = **cast(Interface ***)*p;
+        Object     o  = cast(Object)(*p - pi.offset);
+
+        _d_delclass(&o);
+        *p = null;
+    }
+}
+
+
+// used for deletion
+private extern (D) alias void (*fp_t)(Object);
+
+
+/**
+ *
+ */
+extern (C) void _d_delclass(Object* p)
+{
+    if (*p)
+    {
+        debug(PRINTF) printf("_d_delclass(%p)\n", *p);
+
+        ClassInfo **pc = cast(ClassInfo **)*p;
+        if (*pc)
+        {
+            ClassInfo c = **pc;
+
+            rt_finalize(cast(void*) *p);
+
+            if (c.deallocator)
+            {
+                fp_t fp = cast(fp_t)c.deallocator;
+                (*fp)(*p); // call deallocator
+                *p = null;
+                return;
+            }
+        }
+        else
+        {
+            rt_finalize(cast(void*) *p);
+        }
+        gc_free(cast(void*) *p);
+        *p = null;
+    }
+}
+
+
+/**
+ * Allocate a new array of length elements.
+ * ti is the type of the resulting array, or pointer to element.
+ * (For when the array is initialized to 0)
+ */
+extern (C) ulong _d_newarrayT(TypeInfo ti, size_t length)
+{
+    void* p;
+    ulong result;
+    auto size = ti.next.tsize();                // array element size
+
+    debug(PRINTF) printf("_d_newarrayT(length = x%x, size = %d)\n", length, size);
+    if (length == 0 || size == 0)
+        result = 0;
+    else
+    {
+        version (D_InlineAsm_X86)
+        {
+            asm
+            {
+                mov     EAX,size        ;
+                mul     EAX,length      ;
+                mov     size,EAX        ;
+                jc      Loverflow       ;
+            }
+        }
+        else
+            size *= length;
+        p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        debug(PRINTF) printf(" p = %p\n", p);
+        memset(p, 0, size);
+        result = cast(ulong)length + (cast(ulong)cast(uint)p << 32);
+    }
+    return result;
+
+Loverflow:
+    onOutOfMemoryError();
+}
+
+/**
+ * For when the array has a non-zero initializer.
+ */
+extern (C) ulong _d_newarrayiT(TypeInfo ti, size_t length)
+{
+    ulong result;
+    auto size = ti.next.tsize();                // array element size
+
+    debug(PRINTF) printf("_d_newarrayiT(length = %d, size = %d)\n", length, size);
+
+    if (length == 0 || size == 0)
+        result = 0;
+    else
+    {
+        auto initializer = ti.next.init();
+        auto isize = initializer.length;
+        auto q = initializer.ptr;
+        version (D_InlineAsm_X86)
+        {
+            asm
+            {
+                mov     EAX,size        ;
+                mul     EAX,length      ;
+                mov     size,EAX        ;
+                jc      Loverflow       ;
+            }
+        }
+        else
+            size *= length;
+        auto p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        debug(PRINTF) printf(" p = %p\n", p);
+        if (isize == 1)
+            memset(p, *cast(ubyte*)q, size);
+        else if (isize == int.sizeof)
+        {
+            int init = *cast(int*)q;
+            size /= int.sizeof;
+            for (size_t u = 0; u < size; u++)
+            {
+                (cast(int*)p)[u] = init;
+            }
+        }
+        else
+        {
+            for (size_t u = 0; u < size; u += isize)
+            {
+                memcpy(p + u, q, isize);
+            }
+        }
+        va_end(q);
+        result = cast(ulong)length + (cast(ulong)cast(uint)p << 32);
+    }
+    return result;
+
+Loverflow:
+    onOutOfMemoryError();
+}
+
+/**
+ *
+ */
+extern (C) ulong _d_newarraymT(TypeInfo ti, int ndims, ...)
+{
+    ulong result;
+
+    debug(PRINTF) printf("_d_newarraymT(ndims = %d)\n", ndims);
+    if (ndims == 0)
+        result = 0;
+    else
+    {   va_list q;
+        va_start!(int)(q, ndims);
+
+        void[] foo(TypeInfo ti, size_t* pdim, int ndims)
+        {
+            size_t dim = *pdim;
+            void[] p;
+
+            debug(PRINTF) printf("foo(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, ndims);
+            if (ndims == 1)
+            {
+                auto r = _d_newarrayT(ti, dim);
+                p = *cast(void[]*)(&r);
+            }
+            else
+            {
+                p = gc_malloc(dim * (void[]).sizeof + 1)[0 .. dim];
+                for (int i = 0; i < dim; i++)
+                {
+                    (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1);
+                }
+            }
+            return p;
+        }
+
+        size_t* pdim = cast(size_t *)q;
+        result = cast(ulong)foo(ti, pdim, ndims);
+        debug(PRINTF) printf("result = %llx\n", result);
+
+        version (none)
+        {
+            for (int i = 0; i < ndims; i++)
+            {
+                printf("index %d: %d\n", i, va_arg!(int)(q));
+            }
+        }
+        va_end(q);
+    }
+    return result;
+}
+
+
+/**
+ *
+ */
+extern (C) ulong _d_newarraymiT(TypeInfo ti, int ndims, ...)
+{
+    ulong result;
+
+    debug(PRINTF) printf("_d_newarraymiT(ndims = %d)\n", ndims);
+    if (ndims == 0)
+        result = 0;
+    else
+    {
+        va_list q;
+        va_start!(int)(q, ndims);
+
+        void[] foo(TypeInfo ti, size_t* pdim, int ndims)
+        {
+            size_t dim = *pdim;
+            void[] p;
+
+            if (ndims == 1)
+            {
+                auto r = _d_newarrayiT(ti, dim);
+                p = *cast(void[]*)(&r);
+            }
+            else
+            {
+                p = gc_malloc(dim * (void[]).sizeof + 1)[0 .. dim];
+                for (int i = 0; i < dim; i++)
+                {
+                    (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1);
+                }
+            }
+            return p;
+        }
+
+        size_t* pdim = cast(size_t *)q;
+        result = cast(ulong)foo(ti, pdim, ndims);
+        debug(PRINTF) printf("result = %llx\n", result);
+
+        version (none)
+        {
+            for (int i = 0; i < ndims; i++)
+            {
+                printf("index %d: %d\n", i, va_arg!(int)(q));
+                printf("init = %d\n", va_arg!(int)(q));
+            }
+        }
+        va_end(q);
+    }
+    return result;
+}
+
+
+/**
+ *
+ */
+struct Array
+{
+    size_t length;
+    byte*  data;
+}
+
+
+/**
+ * This function has been replaced by _d_delarray_t
+ */
+extern (C) void _d_delarray(Array *p)
+{
+    if (p)
+    {
+        assert(!p.length || p.data);
+
+        if (p.data)
+            gc_free(p.data);
+        p.data = null;
+        p.length = 0;
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void _d_delarray_t(Array *p, TypeInfo ti)
+{
+    if (p)
+    {
+        assert(!p.length || p.data);
+        if (p.data)
+        {
+            if (ti)
+            {
+                // Call destructors on all the sub-objects
+                auto sz = ti.tsize();
+                auto pe = p.data;
+                auto pend = pe + p.length * sz;
+                while (pe != pend)
+                {
+                    pend -= sz;
+                    ti.destroy(pend);
+                }
+            }
+            gc_free(p.data);
+        }
+        p.data = null;
+        p.length = 0;
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void _d_delmemory(void* *p)
+{
+    if (*p)
+    {
+        gc_free(*p);
+        *p = null;
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void _d_callinterfacefinalizer(void *p)
+{
+    if (p)
+    {
+        Interface *pi = **cast(Interface ***)p;
+        Object o = cast(Object)(p - pi.offset);
+        rt_finalize(cast(void*)o);
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void _d_callfinalizer(void* p)
+{
+    rt_finalize( p );
+}
+
+
+/**
+ *
+ */
+extern (C) void  rt_setCollectHandler(CollectHandler h)
+{
+    collectHandler = h;
+}
+
+
+/**
+ *
+ */
+extern (C) void rt_finalize(void* p, bool det = true)
+{
+    debug(PRINTF) printf("rt_finalize(p = %p)\n", p);
+
+    if (p) // not necessary if called from gc
+    {
+        ClassInfo** pc = cast(ClassInfo**)p;
+
+        if (*pc)
+        {
+            ClassInfo c = **pc;
+
+            try
+            {
+                if (det || collectHandler is null || collectHandler(cast(Object)p))
+                {
+                    do
+                    {
+                        if (c.destructor)
+                        {
+                            fp_t fp = cast(fp_t)c.destructor;
+                            (*fp)(cast(Object)p); // call destructor
+                        }
+                        c = c.base;
+                    } while (c);
+                }
+                if ((cast(void**)p)[1]) // if monitor is not null
+                    _d_monitordelete(cast(Object)p, det);
+            }
+            catch (Throwable e)
+            {
+                onFinalizeError(**pc, e);
+            }
+            finally
+            {
+                *pc = null; // zero vptr
+            }
+        }
+    }
+}
+
+
+/**
+ * Resize dynamic arrays with 0 initializers.
+ */
+extern (C) byte[] _d_arraysetlengthT(TypeInfo ti, size_t newlength, Array *p)
+in
+{
+    assert(ti);
+    assert(!p.length || p.data);
+}
+body
+{
+    debug(PRINTF)
+    {
+        printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength);
+        if (p)
+            printf("\tp.data = %p, p.length = %d\n", p.data, p.length);
+    }
+
+    byte* newdata = void;
+    if (newlength)
+    {
+	if (newlength <= p.length)
+	{
+	    p.length = newlength;
+	    newdata = p.data;
+	    return newdata[0 .. newlength];
+	}
+	size_t sizeelem = ti.next.tsize();
+        version (D_InlineAsm_X86)
+        {
+            size_t newsize = void;
+
+            asm
+            {
+                mov EAX, newlength;
+                mul EAX, sizeelem;
+                mov newsize, EAX;
+                jc  Loverflow;
+            }
+        }
+        else
+        {
+            size_t newsize = sizeelem * newlength;
+
+            if (newsize / newlength != sizeelem)
+                goto Loverflow;
+        }
+
+        debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength);
+
+        if (p.data)
+        {
+            newdata = p.data;
+            if (newlength > p.length)
+            {
+                size_t size = p.length * sizeelem;
+                auto   info = gc_query(p.data);
+
+                if (info.size <= newsize || info.base != p.data)
+                {
+                    if (info.size >= PAGESIZE && info.base == p.data)
+                    {   // Try to extend in-place
+                        auto u = gc_extend(p.data, (newsize + 1) - info.size, (newsize + 1) - info.size);
+                        if (u)
+                        {
+                            goto L1;
+                        }
+                    }
+                    newdata = cast(byte *)gc_malloc(newsize + 1, info.attr);
+                    newdata[0 .. size] = p.data[0 .. size];
+                }
+             L1:
+                newdata[size .. newsize] = 0;
+            }
+        }
+        else
+        {
+            newdata = cast(byte *)gc_calloc(newsize + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        }
+    }
+    else
+    {
+        newdata = p.data;
+    }
+
+    p.data = newdata;
+    p.length = newlength;
+    return newdata[0 .. newlength];
+
+Loverflow:
+    onOutOfMemoryError();
+}
+
+
+/**
+ * Resize arrays for non-zero initializers.
+ *      p               pointer to array lvalue to be updated
+ *      newlength       new .length property of array
+ *      sizeelem        size of each element of array
+ *      initsize        size of initializer
+ *      ...             initializer
+ */
+extern (C) byte[] _d_arraysetlengthiT(TypeInfo ti, size_t newlength, Array *p)
+in
+{
+    assert(!p.length || p.data);
+}
+body
+{
+    byte* newdata;
+    size_t sizeelem = ti.next.tsize();
+    void[] initializer = ti.next.init();
+    size_t initsize = initializer.length;
+
+    assert(sizeelem);
+    assert(initsize);
+    assert(initsize <= sizeelem);
+    assert((sizeelem / initsize) * initsize == sizeelem);
+
+    debug(PRINTF)
+    {
+        printf("_d_arraysetlengthiT(p = %p, sizeelem = %d, newlength = %d, initsize = %d)\n", p, sizeelem, newlength, initsize);
+        if (p)
+            printf("\tp.data = %p, p.length = %d\n", p.data, p.length);
+    }
+
+    if (newlength)
+    {
+        version (D_InlineAsm_X86)
+        {
+            size_t newsize = void;
+
+            asm
+            {
+                mov     EAX,newlength   ;
+                mul     EAX,sizeelem    ;
+                mov     newsize,EAX     ;
+                jc      Loverflow       ;
+            }
+        }
+        else
+        {
+            size_t newsize = sizeelem * newlength;
+
+            if (newsize / newlength != sizeelem)
+                goto Loverflow;
+        }
+        debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength);
+
+        size_t size = p.length * sizeelem;
+
+        if (p.data)
+        {
+            newdata = p.data;
+            if (newlength > p.length)
+            {
+                auto info = gc_query(p.data);
+
+                if (info.size <= newsize || info.base != p.data)
+                {
+                    if (info.size >= PAGESIZE && info.base == p.data)
+                    {   // Try to extend in-place
+                        auto u = gc_extend(p.data, (newsize + 1) - info.size, (newsize + 1) - info.size);
+                        if (u)
+                        {
+                            goto L1;
+                        }
+                    }
+                    newdata = cast(byte *)gc_malloc(newsize + 1, info.attr);
+                    newdata[0 .. size] = p.data[0 .. size];
+                L1: ;
+                }
+            }
+        }
+        else
+        {
+            newdata = cast(byte *)gc_malloc(newsize + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        }
+
+        auto q = initializer.ptr; // pointer to initializer
+
+        if (newsize > size)
+        {
+            if (initsize == 1)
+            {
+                debug(PRINTF) printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q);
+                newdata[size .. newsize] = *(cast(byte*)q);
+            }
+            else
+            {
+                for (size_t u = size; u < newsize; u += initsize)
+                {
+                    memcpy(newdata + u, q, initsize);
+                }
+            }
+        }
+    }
+    else
+    {
+        newdata = p.data;
+    }
+
+    p.data = newdata;
+    p.length = newlength;
+    return newdata[0 .. newlength];
+
+Loverflow:
+    onOutOfMemoryError();
+}
+
+
+/**
+ * Append y[] to array x[].
+ * size is size of each array element.
+ */
+extern (C) long _d_arrayappendT(TypeInfo ti, Array *px, byte[] y)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    auto info = gc_query(px.data);
+    auto length = px.length;
+    auto newlength = length + y.length;
+    auto newsize = newlength * sizeelem;
+
+    if (info.size < newsize || info.base != px.data)
+    {   byte* newdata;
+
+        if (info.size >= PAGESIZE && info.base == px.data)
+        {   // Try to extend in-place
+            auto u = gc_extend(px.data, (newsize + 1) - info.size, (newsize + 1) - info.size);
+            if (u)
+            {
+                goto L1;
+            }
+        }
+        newdata = cast(byte *)gc_malloc(newCapacity(newlength, sizeelem) + 1, info.attr);
+        memcpy(newdata, px.data, length * sizeelem);
+        px.data = newdata;
+    }
+  L1:
+    px.length = newlength;
+    memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem);
+    return *cast(long*)px;
+}
+
+
+/**
+ *
+ */
+size_t newCapacity(size_t newlength, size_t size)
+{
+    version(none)
+    {
+        size_t newcap = newlength * size;
+    }
+    else
+    {
+        /*
+         * Better version by Dave Fladebo:
+         * This uses an inverse logorithmic algorithm to pre-allocate a bit more
+         * space for larger arrays.
+         * - Arrays smaller than PAGESIZE bytes are left as-is, so for the most
+         * common cases, memory allocation is 1 to 1. The small overhead added
+         * doesn't affect small array perf. (it's virtually the same as
+         * current).
+         * - Larger arrays have some space pre-allocated.
+         * - As the arrays grow, the relative pre-allocated space shrinks.
+         * - The logorithmic algorithm allocates relatively more space for
+         * mid-size arrays, making it very fast for medium arrays (for
+         * mid-to-large arrays, this turns out to be quite a bit faster than the
+         * equivalent realloc() code in C, on Linux at least. Small arrays are
+         * just as fast as GCC).
+         * - Perhaps most importantly, overall memory usage and stress on the GC
+         * is decreased significantly for demanding environments.
+         */
+        size_t newcap = newlength * size;
+        size_t newext = 0;
+
+        if (newcap > PAGESIZE)
+        {
+            //double mult2 = 1.0 + (size / log10(pow(newcap * 2.0,2.0)));
+
+            // redo above line using only integer math
+
+            static int log2plus1(size_t c)
+            {   int i;
+
+                if (c == 0)
+                    i = -1;
+                else
+                    for (i = 1; c >>= 1; i++)
+                    {
+                    }
+                return i;
+            }
+
+            /* The following setting for mult sets how much bigger
+             * the new size will be over what is actually needed.
+             * 100 means the same size, more means proportionally more.
+             * More means faster but more memory consumption.
+             */
+            //long mult = 100 + (1000L * size) / (6 * log2plus1(newcap));
+            long mult = 100 + (1000L * size) / log2plus1(newcap);
+
+            // testing shows 1.02 for large arrays is about the point of diminishing return
+            if (mult < 102)
+                mult = 102;
+            newext = cast(size_t)((newcap * mult) / 100);
+            newext -= newext % size;
+            debug(PRINTF) printf("mult: %2.2f, alloc: %2.2f\n",mult/100.0,newext / cast(double)size);
+        }
+        newcap = newext > newcap ? newext : newcap;
+        debug(PRINTF) printf("newcap = %d, newlength = %d, size = %d\n", newcap, newlength, size);
+    }
+    return newcap;
+}
+
+
+/**
+ *
+ */
+extern (C) byte[] _d_arrayappendcT(TypeInfo ti, inout byte[] x, ...)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    auto info = gc_query(x.ptr);
+    auto length = x.length;
+    auto newlength = length + 1;
+    auto newsize = newlength * sizeelem;
+
+    assert(info.size == 0 || length * sizeelem <= info.size);
+
+    debug(PRINTF) printf("_d_arrayappendcT(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, info.size);
+
+    if (info.size <= newsize || info.base != x.ptr)
+    {   byte* newdata;
+
+        if (info.size >= PAGESIZE && info.base == x.ptr)
+        {   // Try to extend in-place
+            auto u = gc_extend(x.ptr, (newsize + 1) - info.size, (newsize + 1) - info.size);
+            if (u)
+            {
+                goto L1;
+            }
+        }
+        debug(PRINTF) printf("_d_arrayappendcT(length = %d, newlength = %d, cap = %d)\n", length, newlength, info.size);
+        auto newcap = newCapacity(newlength, sizeelem);
+        assert(newcap >= newlength * sizeelem);
+        newdata = cast(byte *)gc_malloc(newcap + 1, info.attr);
+        memcpy(newdata, x.ptr, length * sizeelem);
+        (cast(void**)(&x))[1] = newdata;
+    }
+  L1:
+    byte *argp = cast(byte *)(&ti + 2);
+
+    *cast(size_t *)&x = newlength;
+    x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem];
+    assert((cast(size_t)x.ptr & 15) == 0);
+    assert(gc_sizeOf(x.ptr) > x.length * sizeelem);
+    return x;
+}
+
+
+/**
+ *
+ */
+extern (C) byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y)
+out (result)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, sizeelem, result.length, result.ptr);
+    assert(result.length == x.length + y.length);
+    for (size_t i = 0; i < x.length * sizeelem; i++)
+        assert((cast(byte*)result)[i] == (cast(byte*)x)[i]);
+    for (size_t i = 0; i < y.length * sizeelem; i++)
+        assert((cast(byte*)result)[x.length * sizeelem + i] == (cast(byte*)y)[i]);
+
+    size_t cap = gc_sizeOf(result.ptr);
+    assert(!cap || cap > result.length * sizeelem);
+}
+body
+{
+    version (none)
+    {
+        /* Cannot use this optimization because:
+         *  char[] a, b;
+         *  char c = 'a';
+         *  b = a ~ c;
+         *  c = 'b';
+         * will change the contents of b.
+         */
+        if (!y.length)
+            return x;
+        if (!x.length)
+            return y;
+    }
+
+    debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p)\n", x.length, x.ptr, y.length, y.ptr);
+    auto sizeelem = ti.next.tsize();            // array element size
+    debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d)\n", x.length, x.ptr, y.length, y.ptr, sizeelem);
+    size_t xlen = x.length * sizeelem;
+    size_t ylen = y.length * sizeelem;
+    size_t len  = xlen + ylen;
+
+    if (!len)
+        return null;
+
+    byte* p = cast(byte*)gc_malloc(len + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+    memcpy(p, x.ptr, xlen);
+    memcpy(p + xlen, y.ptr, ylen);
+    p[len] = 0;
+    return p[0 .. x.length + y.length];
+}
+
+
+/**
+ *
+ */
+extern (C) byte[] _d_arraycatnT(TypeInfo ti, uint n, ...)
+{   void* a;
+    size_t length;
+    byte[]* p;
+    uint i;
+    byte[] b;
+    auto size = ti.next.tsize(); // array element size
+
+    p = cast(byte[]*)(&n + 1);
+
+    for (i = 0; i < n; i++)
+    {
+        b = *p++;
+        length += b.length;
+    }
+    if (!length)
+        return null;
+
+    a = gc_malloc(length * size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+    p = cast(byte[]*)(&n + 1);
+
+    uint j = 0;
+    for (i = 0; i < n; i++)
+    {
+        b = *p++;
+        if (b.length)
+        {
+            memcpy(a + j, b.ptr, b.length * size);
+            j += b.length * size;
+        }
+    }
+
+    byte[] result;
+    *cast(int *)&result = length;       // jam length
+    (cast(void **)&result)[1] = a;      // jam ptr
+    return result;
+}
+
+
+/**
+ *
+ */
+extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    void* result;
+
+    debug(PRINTF) printf("_d_arrayliteralT(sizeelem = %d, length = %d)\n", sizeelem, length);
+    if (length == 0 || sizeelem == 0)
+        result = null;
+    else
+    {
+        result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+
+        va_list q;
+        va_start!(size_t)(q, length);
+
+        size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1);
+
+        if (stacksize == sizeelem)
+        {
+            memcpy(result, q, length * sizeelem);
+        }
+        else
+        {
+            for (size_t i = 0; i < length; i++)
+            {
+                memcpy(result + i * sizeelem, q, sizeelem);
+                q += stacksize;
+            }
+        }
+
+        va_end(q);
+    }
+    return result;
+}
+
+
+/**
+ * Support for array.dup property.
+ */
+struct Array2
+{
+    size_t length;
+    void*  ptr;
+}
+
+
+/**
+ *
+ */
+extern (C) long _adDupT(TypeInfo ti, Array2 a)
+out (result)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    assert(memcmp((*cast(Array2*)&result).ptr, a.ptr, a.length * sizeelem) == 0);
+}
+body
+{
+    Array2 r;
+
+    if (a.length)
+    {
+        auto sizeelem = ti.next.tsize();                // array element size
+        auto size = a.length * sizeelem;
+        r.ptr = gc_malloc(size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        r.length = a.length;
+        memcpy(r.ptr, a.ptr, size);
+    }
+    return *cast(long*)(&r);
+}
+
+
+unittest
+{
+    int[] a;
+    int[] b;
+    int i;
+
+    a = new int[3];
+    a[0] = 1; a[1] = 2; a[2] = 3;
+    b = a.dup;
+    assert(b.length == 3);
+    for (i = 0; i < 3; i++)
+        assert(b[i] == i + 1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/llmath.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,531 @@
+/**
+ * Support for 64-bit longs.
+ *
+ * Copyright: Copyright Digital Mars 1993 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 1993 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.llmath;
+
+extern (C):
+
+
+/***************************************
+ * Unsigned long divide.
+ * Input:
+ *      [EDX,EAX],[ECX,EBX]
+ * Output:
+ *      [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
+ *      [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
+ */
+
+void __ULDIV__()
+{
+    asm
+    {
+        naked                   ;
+        test    ECX,ECX         ;
+        jz      uldiv           ;
+
+        // if ECX > EDX, then quotient is 0 and remainder is [EDX,EAX]
+        cmp     ECX,EDX         ;
+        ja      quo0            ;
+
+        test    ECX,ECX         ;
+        js      Lleft           ;
+
+        /* We have n>d, and know that n/d will fit in 32 bits.
+         * d will be left justified if we shift it left s bits.
+         * [d1,d0] <<= s
+         * [n2,n1,n0] = [n1,n0] << s
+         *
+         * Use one divide, by this reasoning:
+         * ([n2,n1]<<32 + n0)/(d1<<32 + d0)
+         * becomes:
+         * ([n2,n1]<<32)/(d1<<32 + d0) + n0/(d1<<32 + d0)
+         * The second divide is always 0.
+         * Ignore the d0 in the first divide, which will yield a quotient
+         * that might be too high by 1 (because d1 is left justified).
+         * We can tell if it's too big if:
+         *  q*[d1,d0] > [n2,n1,n0]
+         * which is:
+         *  q*[d1,d0] > [[q*[d1,0]+q%[d1,0],n1,n0]
+         * If we subtract q*[d1,0] from both sides, we get:
+         *  q*d0 > [[n2,n1]%d1,n0]
+         * So if it is too big by one, reduce q by one to q'=q-one.
+         * Compute remainder as:
+         *  r = ([n1,n0] - q'*[d1,d0]) >> s
+         * Again, we can subtract q*[d1,0]:
+         *  r = ([n1,n0] - q*[d1,0] - (q'*[d1,d0] - q*[d1,0])) >> s
+         *  r = ([[n2,n1]%d1,n0] + (q*[d1,0] - (q - one)*[d1,d0])) >> s
+         *  r = ([[n2,n1]%d1,n0] + (q*[d1,0] - [d1 *(q-one),d0*(1-q)])) >> s
+         *  r = ([[n2,n1]%d1,n0] + [d1 *one,d0*(one-q)])) >> s
+         */
+
+        push    EBP             ;
+        push    ESI             ;
+        push    EDI             ;
+
+        mov     ESI,EDX         ;
+        mov     EDI,EAX         ;
+        mov     EBP,ECX         ;
+
+        bsr     EAX,ECX         ;       // EAX is now 30..0
+        xor     EAX,0x1F        ;       // EAX is now 1..31
+        mov     CH,AL           ;
+        neg     EAX             ;
+        add     EAX,32          ;
+        mov     CL,AL           ;
+
+        mov     EAX,EBX         ;
+        shr     EAX,CL          ;
+        xchg    CH,CL           ;
+        shl     EBP,CL          ;
+        or      EBP,EAX         ;
+        shl     EBX,CL          ;
+
+        mov     EDX,ESI         ;
+        xchg    CH,CL           ;
+        shr     EDX,CL          ;
+
+        mov     EAX,EDI         ;
+        shr     EAX,CL          ;
+        xchg    CH,CL           ;
+        shl     EDI,CL          ;
+        shl     ESI,CL          ;
+        or      EAX,ESI         ;
+
+        div     EBP             ;
+        push    EBP             ;
+        mov     EBP,EAX         ;
+        mov     ESI,EDX         ;
+
+        mul     EBX             ;
+        cmp     EDX,ESI         ;
+        ja      L1              ;
+        jb      L2              ;
+        cmp     EAX,EDI         ;
+        jbe     L2              ;
+L1:     dec     EBP             ;
+        sub     EAX,EBX         ;
+        sbb     EDX,0[ESP]      ;
+L2:
+        add     ESP,4           ;
+        sub     EDI,EAX         ;
+        sbb     ESI,EDX         ;
+        mov     EAX,ESI         ;
+        xchg    CH,CL           ;
+        shl     EAX,CL          ;
+        xchg    CH,CL           ;
+        shr     EDI,CL          ;
+        or      EDI,EAX         ;
+        shr     ESI,CL          ;
+        mov     EBX,EDI         ;
+        mov     ECX,ESI         ;
+        mov     EAX,EBP         ;
+        xor     EDX,EDX         ;
+
+        pop     EDI             ;
+        pop     ESI             ;
+        pop     EBP             ;
+        ret                     ;
+
+uldiv:  test    EDX,EDX         ;
+        jnz     D3              ;
+        // Both high words are 0, we can use the DIV instruction
+        div     EBX             ;
+        mov     EBX,EDX         ;
+        mov     EDX,ECX         ;       // EDX = ECX = 0
+        ret                     ;
+
+        even                    ;
+D3:     // Divide [EDX,EAX] by EBX
+        mov     ECX,EAX         ;
+        mov     EAX,EDX         ;
+        xor     EDX,EDX         ;
+        div     EBX             ;
+        xchg    ECX,EAX         ;
+        div     EBX             ;
+        // ECX,EAX = result
+        // EDX = remainder
+        mov     EBX,EDX         ;
+        mov     EDX,ECX         ;
+        xor     ECX,ECX         ;
+        ret                     ;
+
+quo0:   // Quotient is 0
+        // Remainder is [EDX,EAX]
+        mov     EBX,EAX         ;
+        mov     ECX,EDX         ;
+        xor     EAX,EAX         ;
+        xor     EDX,EDX         ;
+        ret                     ;
+
+Lleft:  // The quotient is 0 or 1 and EDX >= ECX
+        cmp     EDX,ECX         ;
+        ja      quo1            ;       // [EDX,EAX] > [ECX,EBX]
+        // EDX == ECX
+        cmp     EAX,EBX         ;
+        jb      quo0            ;
+
+quo1:   // Quotient is 1
+        // Remainder is [EDX,EAX] - [ECX,EBX]
+        sub     EAX,EBX         ;
+        sbb     EDX,ECX         ;
+        mov     EBX,EAX         ;
+        mov     ECX,EDX         ;
+        mov     EAX,1           ;
+        xor     EDX,EDX         ;
+        ret                     ;
+    }
+}
+
+
+/***************************************
+ * Signed long divide.
+ * Input:
+ *      [EDX,EAX],[ECX,EBX]
+ * Output:
+ *      [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
+ *      [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
+ *      ESI,EDI destroyed
+ */
+
+void __LDIV__()
+{
+    asm
+    {
+        naked                   ;
+        test    EDX,EDX         ;       // [EDX,EAX] negative?
+        jns     L10             ;       // no
+        //neg64 EDX,EAX         ;       // [EDX,EAX] = -[EDX,EAX]
+          neg   EDX             ;
+          neg   EAX             ;
+          sbb   EDX,0           ;
+        test    ECX,ECX         ;       // [ECX,EBX] negative?
+        jns     L11             ;       // no
+        //neg64 ECX,EBX         ;
+          neg   ECX             ;
+          neg   EBX             ;
+          sbb   ECX,0           ;
+        call    __ULDIV__       ;
+        //neg64 ECX,EBX         ;       // remainder same sign as dividend
+          neg   ECX             ;
+          neg   EBX             ;
+          sbb   ECX,0           ;
+        ret                     ;
+
+L11:    call    __ULDIV__       ;
+        //neg64 ECX,EBX         ;       // remainder same sign as dividend
+          neg   ECX             ;
+          neg   EBX             ;
+          sbb   ECX,0           ;
+        //neg64 EDX,EAX         ;       // quotient is negative
+          neg   EDX             ;
+          neg   EAX             ;
+          sbb   EDX,0           ;
+        ret                     ;
+
+L10:    test    ECX,ECX         ;       // [ECX,EBX] negative?
+        jns     L12             ;       // no (all is positive)
+        //neg64 ECX,EBX         ;
+          neg   ECX             ;
+          neg   EBX             ;
+          sbb   ECX,0           ;
+        call    __ULDIV__       ;
+        //neg64 EDX,EAX         ;       // quotient is negative
+          neg   EDX             ;
+          neg   EAX             ;
+          sbb   EDX,0           ;
+        ret                     ;
+
+L12:    jmp     __ULDIV__       ;
+    }
+}
+
+
+/***************************************
+ * Compare [EDX,EAX] with [ECX,EBX]
+ * Signed
+ * Returns result in flags
+ */
+
+void __LCMP__()
+{
+    asm
+    {
+        naked                   ;
+        cmp     EDX,ECX         ;
+        jne     C1              ;
+        push    EDX             ;
+        xor     EDX,EDX         ;
+        cmp     EAX,EBX         ;
+        jz      C2              ;
+        ja      C3              ;
+        dec     EDX             ;
+        pop     EDX             ;
+        ret                     ;
+
+C3:     inc     EDX             ;
+C2:     pop     EDX             ;
+C1:     ret                     ;
+    }
+}
+
+
+
+
+// Convert ulong to real
+
+private __gshared real adjust = cast(real)0x800_0000_0000_0000 * 0x10;
+
+real __U64_LDBL()
+{
+    version (OSX)
+    {   /* OSX version has to be concerned about 16 byte stack
+         * alignment and the inability to reference the data segment
+         * because of PIC.
+         */
+        asm
+        {   naked                               ;
+            push        EDX                     ;
+            push        EAX                     ;
+            and         dword ptr 4[ESP], 0x7FFFFFFF    ;
+            fild        qword ptr [ESP]         ;
+            test        EDX,EDX                 ;
+            jns         L1                      ;
+            push        0x0000403e              ;
+            push        0x80000000              ;
+            push        0                       ;
+            fld         real ptr [ESP]          ; // adjust
+            add         ESP,12                  ;
+            faddp       ST(1), ST               ;
+        L1:                                     ;
+            add         ESP, 8                  ;
+            ret                                 ;
+        }
+    }
+    else
+    {
+        asm
+        {   naked                               ;
+            push        EDX                     ;
+            push        EAX                     ;
+            and         dword ptr 4[ESP], 0x7FFFFFFF    ;
+            fild        qword ptr [ESP]         ;
+            test        EDX,EDX                 ;
+            jns         L1                      ;
+            fld         real ptr adjust         ;
+            faddp       ST(1), ST               ;
+        L1:                                     ;
+            add         ESP, 8                  ;
+            ret                                 ;
+        }
+    }
+}
+
+// Same as __U64_LDBL, but return result as double in [EDX,EAX]
+ulong __ULLNGDBL()
+{
+    asm
+    {   naked                                   ;
+        call __U64_LDBL                         ;
+        sub  ESP,8                              ;
+        fstp double ptr [ESP]                   ;
+        pop  EAX                                ;
+        pop  EDX                                ;
+        ret                                     ;
+    }
+}
+
+// Convert double to ulong
+
+private __gshared short roundTo0 = 0xFBF;
+
+ulong __DBLULLNG()
+{
+    // BUG: should handle NAN's and overflows
+    version (OSX)
+    {
+        asm
+        {   naked                               ;
+            push        0xFBF                   ; // roundTo0
+            push        0x0000403e              ;
+            push        0x80000000              ;
+            push        0                       ; // adjust
+            push        EDX                     ;
+            push        EAX                     ;
+            fld         double ptr [ESP]        ;
+            sub         ESP,8                   ;
+            fld         real ptr 16[ESP]        ; // adjust
+            fcomp                               ;
+            fstsw       AX                      ;
+            fstcw       8[ESP]                  ;
+            fldcw       28[ESP]                 ; // roundTo0
+            sahf                                ;
+            jae         L1                      ;
+            fld         real ptr 16[ESP]        ; // adjust
+            fsubp       ST(1), ST               ;
+            fistp       qword ptr [ESP]         ;
+            pop         EAX                     ;
+            pop         EDX                     ;
+            fldcw       [ESP]                   ;
+            add         ESP,24                  ;
+            add         EDX,0x8000_0000         ;
+            ret                                 ;
+        L1:                                     ;
+            fistp       qword ptr [ESP]         ;
+            pop         EAX                     ;
+            pop         EDX                     ;
+            fldcw       [ESP]                   ;
+            add         ESP,24                  ;
+            ret                                 ;
+        }
+    }
+    else
+    {
+        asm
+        {   naked                               ;
+            push        EDX                     ;
+            push        EAX                     ;
+            fld         double ptr [ESP]        ;
+            sub         ESP,8                   ;
+            fld         real ptr adjust         ;
+            fcomp                               ;
+            fstsw       AX                      ;
+            fstcw       8[ESP]                  ;
+            fldcw       roundTo0                ;
+            sahf                                ;
+            jae         L1                      ;
+            fld         real ptr adjust         ;
+            fsubp       ST(1), ST               ;
+            fistp       qword ptr [ESP]         ;
+            pop         EAX                     ;
+            pop         EDX                     ;
+            fldcw       [ESP]                   ;
+            add         ESP,8                   ;
+            add         EDX,0x8000_0000         ;
+            ret                                 ;
+        L1:                                     ;
+            fistp       qword ptr [ESP]         ;
+            pop         EAX                     ;
+            pop         EDX                     ;
+            fldcw       [ESP]                   ;
+            add         ESP,8                   ;
+            ret                                 ;
+        }
+    }
+}
+
+// Convert double in ST0 to uint
+
+uint __DBLULNG()
+{
+    // BUG: should handle NAN's and overflows
+    version (OSX)
+    {
+        asm
+        {   naked                               ;
+            push        0xFBF                   ; // roundTo0
+            sub         ESP,12                  ;
+            fstcw       8[ESP]                  ;
+            fldcw       12[ESP]                 ; // roundTo0
+            fistp       qword ptr [ESP]         ;
+            fldcw       8[ESP]                  ;
+            pop         EAX                     ;
+            add         ESP,12                  ;
+            ret                                 ;
+        }
+    }
+    else
+    {
+        asm
+        {   naked                               ;
+            sub         ESP,16                  ;
+            fstcw       8[ESP]                  ;
+            fldcw       roundTo0                ;
+            fistp       qword ptr [ESP]         ;
+            fldcw       8[ESP]                  ;
+            pop         EAX                     ;
+            add         ESP,12                  ;
+            ret                                 ;
+        }
+    }
+}
+
+// Convert real in ST0 to ulong
+
+ulong __LDBLULLNG()
+{
+    version (OSX)
+    {
+	asm
+	{   naked				;
+	    push	0xFBF			; // roundTo0
+	    push	0x0000403e		;
+	    push	0x80000000		;
+	    push	0			; // adjust
+	    sub		ESP,16			;
+	    fld		real ptr 16[ESP]	; // adjust
+	    fcomp				;
+	    fstsw	AX			;
+	    fstcw	8[ESP]			;
+	    fldcw	28[ESP]			; // roundTo0
+	    sahf				;
+	    jae		L1			;
+	    fld		real ptr 16[ESP]	; // adjust
+	    fsubp	ST(1), ST		;
+	    fistp	qword ptr [ESP]		;
+	    pop		EAX			;
+	    pop		EDX			;
+	    fldcw	[ESP]			;
+	    add		ESP,24			;
+	    add		EDX,0x8000_0000		;
+	    ret					;
+	L1:					;
+	    fistp	qword ptr [ESP]		;
+	    pop		EAX			;
+	    pop		EDX			;
+	    fldcw	[ESP]			;
+	    add		ESP,24			;
+	    ret					;
+	}
+    }
+    else
+    {
+	asm
+	{   naked				;
+	    sub		ESP,16			;
+	    fld		real ptr adjust		;
+	    fcomp				;
+	    fstsw	AX			;
+	    fstcw	8[ESP]			;
+	    fldcw	roundTo0		;
+	    sahf				;
+	    jae		L1			;
+	    fld		real ptr adjust		;
+	    fsubp	ST(1), ST		;
+	    fistp	qword ptr [ESP]		;
+	    pop		EAX			;
+	    pop		EDX			;
+	    fldcw	[ESP]			;
+	    add		ESP,8			;
+	    add		EDX,0x8000_0000		;
+	    ret					;
+	L1:					;
+	    fistp	qword ptr [ESP]		;
+	    pop		EAX			;
+	    pop		EDX			;
+	    fldcw	[ESP]			;
+	    add		ESP,8			;
+	    ret					;
+	}
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/mars.h	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,105 @@
+/**
+ * Common declarations for runtime implementation.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#include <stddef.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+struct ClassInfo;
+struct Vtbl;
+
+typedef struct Vtbl
+{
+    size_t len;
+    void **vptr;
+} Vtbl;
+
+typedef struct Interface
+{
+    struct ClassInfo *classinfo;
+    struct Vtbl vtbl;
+    int offset;
+} Interface;
+
+typedef struct Object
+{
+    void **vptr;
+    void *monitor;
+} Object;
+
+typedef struct ClassInfo
+{
+    Object object;
+
+    size_t initlen;
+    void *init;
+
+    size_t namelen;
+    char *name;
+
+    Vtbl vtbl;
+
+    size_t interfacelen;
+    Interface *interfaces;
+
+    struct ClassInfo *baseClass;
+
+    void *destructor;
+    void *invariant;
+
+    int flags;
+} ClassInfo;
+
+typedef struct Throwable
+{
+    Object object;
+
+    size_t msglen;
+    char*  msg;
+
+    size_t filelen;
+    char*  file;
+
+    size_t line;
+
+    struct Interface *info;
+    struct Throwable *next;
+} Throwable;
+
+typedef struct Array
+{
+    size_t length;
+    void *ptr;
+} Array;
+
+typedef struct Delegate
+{
+    void *thisptr;
+    void (*funcptr)();
+} Delegate;
+
+void _d_monitorenter(Object *h);
+void _d_monitorexit(Object *h);
+
+int _d_isbaseof(ClassInfo *b, ClassInfo *c);
+Object *_d_dynamic_cast(Object *o, ClassInfo *ci);
+
+Object * _d_newclass(ClassInfo *ci);
+void _d_delclass(Object **p);
+
+void _d_OutOfMemory();
+
+#if __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/memory.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,213 @@
+/**
+ * This module exposes functionality for inspecting and manipulating memory.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.memory;
+
+
+private
+{
+    version( linux )
+    {
+        version = SimpleLibcStackEnd;
+
+        version( SimpleLibcStackEnd )
+        {
+            extern (C) extern __gshared void* __libc_stack_end;
+        }
+    }
+    version( FreeBSD )
+    {
+        version = SimpleLibcStackEnd;
+
+        version( SimpleLibcStackEnd )
+        {
+            extern (C) extern __gshared void* __libc_stack_end;
+        }
+    }
+    version( Solaris )
+    {
+        version = SimpleLibcStackEnd;
+
+        version( SimpleLibcStackEnd )
+        {
+            extern (C) extern __gshared void* __libc_stack_end;
+        }
+    }
+    extern (C) void gc_addRange( void* p, size_t sz );
+    extern (C) void gc_removeRange( void* p );
+}
+
+
+/**
+ *
+ */
+extern (C) void* rt_stackBottom()
+{
+    version( Windows )
+    {
+        asm
+        {
+            naked;
+            mov EAX,FS:4;
+            ret;
+        }
+    }
+    else version( linux )
+    {
+        version( SimpleLibcStackEnd )
+        {
+            return __libc_stack_end;
+        }
+        else
+        {
+            // See discussion: http://autopackage.org/forums/viewtopic.php?t=22
+            static void** libc_stack_end;
+
+            if( libc_stack_end == libc_stack_end.init )
+            {
+                void* handle = dlopen( null, RTLD_NOW );
+                libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" );
+                dlclose( handle );
+            }
+            return *libc_stack_end;
+        }
+    }
+    else version( OSX )
+    {
+        return cast(void*) 0xc0000000;
+    }
+    else version( FreeBSD )
+    {
+	return __libc_stack_end;
+    }
+    else version( Solaris )
+    {
+	return __libc_stack_end;
+    }
+    else
+    {
+        static assert( false, "Operating system not supported." );
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void* rt_stackTop()
+{
+    version( D_InlineAsm_X86 )
+    {
+        asm
+        {
+            naked;
+            mov EAX, ESP;
+            ret;
+        }
+    }
+    else
+    {
+        static assert( false, "Architecture not supported." );
+    }
+}
+
+
+private
+{
+    version( Windows )
+    {
+        extern (C)
+        {
+	    extern __gshared
+	    {
+		int _xi_a;   // &_xi_a just happens to be start of data segment
+		int _edata;  // &_edata is start of BSS segment
+		int _end;    // &_end is past end of BSS
+	    }
+        }
+    }
+    else version( linux )
+    {
+        extern (C)
+        {
+	    extern __gshared
+	    {
+		int _data;
+		int __data_start;
+		int _end;
+		int _data_start__;
+		int _data_end__;
+		int _bss_start__;
+		int _bss_end__;
+		int __fini_array_end;
+	    }
+        }
+
+            alias __data_start  Data_Start;
+            alias _end          Data_End;
+    }
+    else version( OSX )
+    {
+        extern (C) void _d_osx_image_init();
+    }
+    else version( FreeBSD )
+    {
+        extern (C)
+        {
+	    extern __gshared
+	    {
+		int etext;
+		int _end;
+	    }
+        }
+    }
+    else version( Solaris )
+    {
+        extern (C)
+        {
+	    extern __gshared
+	    {
+		int etext;
+		int _end;
+	    }
+        }
+    }
+}
+
+
+void initStaticDataGC()
+{
+    version( Windows )
+    {
+        gc_addRange( &_xi_a, cast(size_t) &_end - cast(size_t) &_xi_a );
+    }
+    else version( linux )
+    {
+        gc_addRange( &__data_start, cast(size_t) &_end - cast(size_t) &__data_start );
+    }
+    else version( OSX )
+    {
+        _d_osx_image_init();
+    }
+    else version( FreeBSD )
+    {
+        gc_addRange( &etext, cast(size_t) &_end - cast(size_t) &etext );
+    }
+    else version( Solaris )
+    {
+        gc_addRange( &etext, cast(size_t) &_end - cast(size_t) &etext );
+    }
+    else
+    {
+        static assert( false, "Operating system not supported." );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/memory_osx.c	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,75 @@
+/**
+ * This module provides OSX-specific support routines for memory.d.
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifdef __APPLE__
+
+
+#include <mach-o/dyld.h>
+#include <mach-o/getsect.h>
+
+void gc_addRange( void* p, size_t sz );
+void gc_removeRange( void* p );
+
+typedef struct
+{
+    const char* seg;
+    const char* sect;
+} seg_ref;
+
+const static seg_ref data_segs[] = {{SEG_DATA, SECT_DATA},
+                                    {SEG_DATA, SECT_BSS},
+                                    {SEG_DATA, SECT_COMMON}};
+const static int NUM_DATA_SEGS   = sizeof(data_segs) / sizeof(seg_ref);
+
+
+static void on_add_image( const struct mach_header* h, intptr_t slide )
+{
+    const struct section* sect;
+    int i;
+
+    for( i = 0; i < NUM_DATA_SEGS; ++i )
+    {
+        sect = getsectbynamefromheader( h,
+                                        data_segs[i].seg,
+                                        data_segs[i].sect );
+        if( sect == NULL || sect->size == 0 )
+            continue;
+        gc_addRange( (void*) sect->addr + slide, sect->size );
+    }
+}
+
+
+static void on_remove_image( const struct mach_header* h, intptr_t slide )
+{
+    const struct section* sect;
+    int i;
+
+    for( i = 0; i < NUM_DATA_SEGS; ++i )
+    {
+        sect = getsectbynamefromheader( h,
+                                        data_segs[i].seg,
+                                        data_segs[i].sect );
+        if( sect == NULL || sect->size == 0 )
+            continue;
+        gc_removeRange( (void*) sect->addr + slide );
+    }
+}
+
+
+void _d_osx_image_init()
+{
+    _dyld_register_func_for_add_image( &on_add_image );
+    _dyld_register_func_for_remove_image( &on_remove_image );
+}
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/memset.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,109 @@
+/**
+ * Contains a memset implementation used by compiler-generated code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.memset;
+
+extern (C)
+{
+    // Functions from the C library.
+    void *memcpy(void *, void *, size_t);
+}
+
+extern (C):
+
+short *_memset16(short *p, short value, size_t count)
+{
+    short *pstart = p;
+    short *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+
+int *_memset32(int *p, int value, size_t count)
+{
+version (X86)
+{
+    asm
+    {
+        mov     EDI,p           ;
+        mov     EAX,value       ;
+        mov     ECX,count       ;
+        mov     EDX,EDI         ;
+        rep                     ;
+        stosd                   ;
+        mov     EAX,EDX         ;
+    }
+}
+else
+{
+    int *pstart = p;
+    int *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+}
+
+long *_memset64(long *p, long value, size_t count)
+{
+    long *pstart = p;
+    long *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+
+cdouble *_memset128(cdouble *p, cdouble value, size_t count)
+{
+    cdouble *pstart = p;
+    cdouble *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+
+real *_memset80(real *p, real value, size_t count)
+{
+    real *pstart = p;
+    real *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+
+creal *_memset160(creal *p, creal value, size_t count)
+{
+    creal *pstart = p;
+    creal *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+
+void *_memsetn(void *p, void *value, int count, size_t sizelem)
+{   void *pstart = p;
+    int i;
+
+    for (i = 0; i < count; i++)
+    {
+        memcpy(p, value, sizelem);
+        p = cast(void *)(cast(char *)p + sizelem);
+    }
+    return pstart;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/minit.asm	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,85 @@
+;_ minit.asm
+;  Module initialization support.
+; 
+;  Copyright: Copyright Digital Mars 2000 - 2009.
+;  License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+;  Authors:   Walter Bright
+; 
+;           Copyright Digital Mars 2000 - 2009.
+;  Distributed under the Boost Software License, Version 1.0.
+;     (See accompanying file LICENSE_1_0.txt or copy at
+;           http://www.boost.org/LICENSE_1_0.txt)
+;
+include macros.asm
+
+ifdef _WIN32
+  DATAGRP      EQU     FLAT
+else
+  DATAGRP      EQU     DGROUP
+endif
+
+; Provide a default resolution for weak extern records, no way in C
+; to define an omf symbol with a specific value
+public __nullext
+__nullext   equ 0
+
+    extrn   __moduleinfo_array:near
+
+; This bit of assembler is needed because, from C or D, one cannot
+; specify the names of data segments. Why does this matter?
+; All the ModuleInfo pointers are placed into a segment named 'FM'.
+; The order in which they are placed in 'FM' is arbitrarily up to the linker.
+; In order to walk all the pointers, we need to be able to find the
+; beginning and the end of the 'FM' segment.
+; This is done by bracketing the 'FM' segment with two other, empty,
+; segments named 'FMB' and 'FME'. Since this module is the only one that
+; ever refers to 'FMB' and 'FME', we get to control the order in which
+; these segments appear relative to 'FM' by using a GROUP statement.
+; So, we have in memory:
+;   FMB empty segment
+;   FM  contains all the pointers
+;   FME empty segment
+; and finding the limits of FM is as easy as taking the address of FMB
+; and the address of FME.
+
+; These segments bracket FM, which contains the list of ModuleInfo pointers
+FMB     segment dword use32 public 'DATA'
+FMB     ends
+FM      segment dword use32 public 'DATA'
+FM      ends
+FME     segment dword use32 public 'DATA'
+FME     ends
+
+; This leaves room in the _fatexit() list for _moduleDtor()
+XOB     segment dword use32 public 'BSS'
+XOB     ends
+XO      segment dword use32 public 'BSS'
+    dd  ?
+XO      ends
+XOE     segment dword use32 public 'BSS'
+XOE     ends
+
+DGROUP         group   FMB,FM,FME
+
+    begcode minit
+
+; extern (C) void _minit();
+; Converts array of ModuleInfo pointers to a D dynamic array of them,
+; so they can be accessed via D.
+; Result is written to:
+; extern (C) ModuleInfo[] _moduleinfo_array;
+
+    public  __minit
+__minit proc    near
+    mov EDX,offset DATAGRP:FMB
+    mov EAX,offset DATAGRP:FME
+    mov dword ptr __moduleinfo_array+4,EDX
+    sub EAX,EDX         ; size in bytes of FM segment
+    shr EAX,2           ; convert to array length
+    mov dword ptr __moduleinfo_array,EAX
+    ret
+__minit endp
+
+    endcode minit
+
+    end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/monitor.c	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,215 @@
+/**
+ * Contains the implementation for object monitors.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if _WIN32
+#elif linux || __APPLE__
+#define USE_PTHREADS    1
+#else
+#endif
+
+#if _WIN32
+#include <windows.h>
+#endif
+
+#if USE_PTHREADS
+#include <pthread.h>
+#endif
+
+#include "mars.h"
+
+// This is what the monitor reference in Object points to
+typedef struct Monitor
+{
+    void* impl; // for user-level monitors
+    Array devt; // for internal monitors
+
+#if _WIN32
+    CRITICAL_SECTION mon;
+#endif
+
+#if USE_PTHREADS
+    pthread_mutex_t mon;
+#endif
+} Monitor;
+
+#define MONPTR(h)       (&((Monitor *)(h)->monitor)->mon)
+
+static volatile int inited;
+
+/* =============================== Win32 ============================ */
+
+#if _WIN32
+
+static CRITICAL_SECTION _monitor_critsec;
+
+void _STI_monitor_staticctor()
+{
+    if (!inited)
+    {   InitializeCriticalSection(&_monitor_critsec);
+        inited = 1;
+    }
+}
+
+void _STD_monitor_staticdtor()
+{
+    if (inited)
+    {   inited = 0;
+        DeleteCriticalSection(&_monitor_critsec);
+    }
+}
+
+void _d_monitor_create(Object *h)
+{
+    /*
+     * NOTE: Assume this is only called when h->monitor is null prior to the
+     * call.  However, please note that another thread may call this function
+     * at the same time, so we can not assert this here.  Instead, try and
+     * create a lock, and if one already exists then forget about it.
+     */
+
+    //printf("+_d_monitor_create(%p)\n", h);
+    assert(h);
+    Monitor *cs = NULL;
+    EnterCriticalSection(&_monitor_critsec);
+    if (!h->monitor)
+    {
+        cs = (Monitor *)calloc(sizeof(Monitor), 1);
+        assert(cs);
+        InitializeCriticalSection(&cs->mon);
+        h->monitor = (void *)cs;
+        cs = NULL;
+    }
+    LeaveCriticalSection(&_monitor_critsec);
+    if (cs)
+        free(cs);
+    //printf("-_d_monitor_create(%p)\n", h);
+}
+
+void _d_monitor_destroy(Object *h)
+{
+    //printf("+_d_monitor_destroy(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    DeleteCriticalSection(MONPTR(h));
+    free((void *)h->monitor);
+    h->monitor = NULL;
+    //printf("-_d_monitor_destroy(%p)\n", h);
+}
+
+int _d_monitor_lock(Object *h)
+{
+    //printf("+_d_monitor_acquire(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    EnterCriticalSection(MONPTR(h));
+    //printf("-_d_monitor_acquire(%p)\n", h);
+}
+
+void _d_monitor_unlock(Object *h)
+{
+    //printf("+_d_monitor_release(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    LeaveCriticalSection(MONPTR(h));
+    //printf("-_d_monitor_release(%p)\n", h);
+}
+
+#endif
+
+/* =============================== linux ============================ */
+
+#if USE_PTHREADS
+
+#ifndef PTHREAD_MUTEX_RECURSIVE
+#    define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
+#endif
+
+// Includes attribute fixes from David Friedman's GDC port
+
+static pthread_mutex_t _monitor_critsec;
+static pthread_mutexattr_t _monitors_attr;
+
+void _STI_monitor_staticctor()
+{
+    if (!inited)
+    {
+        pthread_mutexattr_init(&_monitors_attr);
+        pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE);
+        pthread_mutex_init(&_monitor_critsec, 0);
+        inited = 1;
+    }
+}
+
+void _STD_monitor_staticdtor()
+{
+    if (inited)
+    {   inited = 0;
+        pthread_mutex_destroy(&_monitor_critsec);
+        pthread_mutexattr_destroy(&_monitors_attr);
+    }
+}
+
+void _d_monitor_create(Object *h)
+{
+    /*
+     * NOTE: Assume this is only called when h->monitor is null prior to the
+     * call.  However, please note that another thread may call this function
+     * at the same time, so we can not assert this here.  Instead, try and
+     * create a lock, and if one already exists then forget about it.
+     */
+
+    //printf("+_d_monitor_create(%p)\n", h);
+    assert(h);
+    Monitor *cs = NULL;
+    pthread_mutex_lock(&_monitor_critsec);
+    if (!h->monitor)
+    {
+        cs = (Monitor *)calloc(sizeof(Monitor), 1);
+        assert(cs);
+        pthread_mutex_init(&cs->mon, & _monitors_attr);
+        h->monitor = (void *)cs;
+        cs = NULL;
+    }
+    pthread_mutex_unlock(&_monitor_critsec);
+    if (cs)
+        free(cs);
+    //printf("-_d_monitor_create(%p)\n", h);
+}
+
+void _d_monitor_destroy(Object *h)
+{
+    //printf("+_d_monitor_destroy(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_destroy(MONPTR(h));
+    free((void *)h->monitor);
+    h->monitor = NULL;
+    //printf("-_d_monitor_destroy(%p)\n", h);
+}
+
+int _d_monitor_lock(Object *h)
+{
+    //printf("+_d_monitor_acquire(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_lock(MONPTR(h));
+    //printf("-_d_monitor_acquire(%p)\n", h);
+}
+
+void _d_monitor_unlock(Object *h)
+{
+    //printf("+_d_monitor_release(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_unlock(MONPTR(h));
+    //printf("-_d_monitor_release(%p)\n", h);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/obj.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,34 @@
+/**
+ * Containts object comparator functions called by generated code.
+ *
+ * Copyright: Copyright Digital Mars 2002 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.obj;
+
+extern (C):
+
+/********************************
+ * Compiler helper for operator == for class objects.
+ */
+
+int _d_obj_eq(Object o1, Object o2)
+{
+    return o1 is o2 || (o1 && o1.opEquals(o2));
+}
+
+
+/********************************
+ * Compiler helper for operator <, <=, >, >= for class objects.
+ */
+
+int _d_obj_cmp(Object o1, Object o2)
+{
+    return o1.opCmp(o2);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/object_.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,1599 @@
+/**
+ * Forms the symbols available to all D programs. Includes Object, which is
+ * the root of the class object hierarchy.  This module is implicitly
+ * imported.
+ * Macros:
+ *      WIKI = Object
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+module object;
+
+private
+{
+    import core.stdc.string;
+    import core.stdc.stdlib;
+    // HACK: This versioning is to provide for the different treatment of
+    //       imports in a normal vs. a -lib build.  It should really be fixed
+    //       correctly before the next release.
+    version (D_Ddoc)
+        import util.string;
+    else
+        import rt.util.string;
+    debug(PRINTF) import core.stdc.stdio;
+
+    extern (C) void onOutOfMemoryError();
+    extern (C) Object _d_newclass(ClassInfo ci);
+}
+
+// NOTE: For some reason, this declaration method doesn't work
+//       in this particular file (and this file only).  It must
+//       be a DMD thing.
+//alias typeof(int.sizeof)                    size_t;
+//alias typeof(cast(void*)0 - cast(void*)0)   ptrdiff_t;
+
+version(X86_64)
+{
+    alias ulong size_t;
+    alias long  ptrdiff_t;
+}
+else
+{
+    alias uint  size_t;
+    alias int   ptrdiff_t;
+}
+
+alias size_t hash_t;
+alias bool equals_t;
+
+alias immutable(char)[]  string;
+alias immutable(wchar)[] wstring;
+alias immutable(dchar)[] dstring;
+
+/**
+ * All D class objects inherit from Object.
+ */
+class Object
+{
+    /**
+     * Convert Object to a human readable string.
+     */
+    string toString()
+    {
+        return this.classinfo.name;
+    }
+
+    /**
+     * Compute hash function for Object.
+     */
+    hash_t toHash()
+    {
+        // BUG: this prevents a compacting GC from working, needs to be fixed
+        return cast(hash_t)cast(void*)this;
+    }
+
+    /**
+     * Compare with another Object obj.
+     * Returns:
+     *  $(TABLE
+     *  $(TR $(TD this &lt; obj) $(TD &lt; 0))
+     *  $(TR $(TD this == obj) $(TD 0))
+     *  $(TR $(TD this &gt; obj) $(TD &gt; 0))
+     *  )
+     */
+    int opCmp(Object o)
+    {
+        // BUG: this prevents a compacting GC from working, needs to be fixed
+        //return cast(int)cast(void*)this - cast(int)cast(void*)o;
+
+        throw new Exception("need opCmp for class " ~ this.classinfo.name);
+        //return this !is o;
+    }
+
+    /**
+     * Returns !=0 if this object does have the same contents as obj.
+     */
+    equals_t opEquals(Object o)
+    {
+        return this is o;
+    }
+
+    interface Monitor
+    {
+        void lock();
+        void unlock();
+    }
+
+    /**
+     * Create instance of class specified by classname.
+     * The class must either have no constructors or have
+     * a default constructor.
+     * Returns:
+     *   null if failed
+     */
+    static Object factory(string classname)
+    {
+        auto ci = ClassInfo.find(classname);
+        if (ci)
+        {
+            return ci.create();
+        }
+        return null;
+    }
+}
+
+/**
+ * Information about an interface.
+ * When an object is accessed via an interface, an Interface* appears as the
+ * first entry in its vtbl.
+ */
+struct Interface
+{
+    ClassInfo   classinfo;  /// .classinfo for this interface (not for containing class)
+    void*[]     vtbl;
+    ptrdiff_t   offset;     /// offset to Interface 'this' from Object 'this'
+}
+
+/**
+ * Runtime type information about a class. Can be retrieved for any class type
+ * or instance by using the .classinfo property.
+ * A pointer to this appears as the first entry in the class's vtbl[].
+ */
+class ClassInfo : Object
+{
+    byte[]      init;           /** class static initializer
+                                 * (init.length gives size in bytes of class)
+                                 */
+    string      name;           /// class name
+    void*[]     vtbl;           /// virtual function pointer table
+    Interface[] interfaces;     /// interfaces this class implements
+    ClassInfo   base;           /// base class
+    void*       destructor;
+    void function(Object) classInvariant;
+    uint        flags;
+    //  1:                      // is IUnknown or is derived from IUnknown
+    //  2:                      // has no possible pointers into GC memory
+    //  4:                      // has offTi[] member
+    //  8:                      // has constructors
+    // 16:                      // has xgetMembers member
+    // 32:                      // has typeinfo member
+    void*       deallocator;
+    OffsetTypeInfo[] offTi;
+    void function(Object) defaultConstructor;   // default Constructor
+    const(MemberInfo[]) function(in char[]) xgetMembers;
+    TypeInfo typeinfo;
+
+    /**
+     * Search all modules for ClassInfo corresponding to classname.
+     * Returns: null if not found
+     */
+    static ClassInfo find(in char[] classname)
+    {
+        foreach (m; ModuleInfo)
+        {
+            //writefln("module %s, %d", m.name, m.localClasses.length);
+            foreach (c; m.localClasses)
+            {
+                //writefln("\tclass %s", c.name);
+                if (c.name == classname)
+                    return c;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Create instance of Object represented by 'this'.
+     */
+    Object create()
+    {
+        if (flags & 8 && !defaultConstructor)
+            return null;
+        Object o = _d_newclass(this);
+        if (flags & 8 && defaultConstructor)
+        {
+            defaultConstructor(o);
+        }
+        return o;
+    }
+
+    /**
+     * Search for all members with the name 'name'.
+     * If name[] is null, return all members.
+     */
+    const(MemberInfo[]) getMembers(in char[] name)
+    {
+        if (flags & 16 && xgetMembers)
+            return xgetMembers(name);
+        return null;
+    }
+}
+
+/**
+ * Array of pairs giving the offset and type information for each
+ * member in an aggregate.
+ */
+struct OffsetTypeInfo
+{
+    size_t   offset;    /// Offset of member from start of object
+    TypeInfo ti;        /// TypeInfo for this member
+}
+
+/**
+ * Runtime type information about a type.
+ * Can be retrieved for any type using a
+ * <a href="../expression.html#typeidexpression">TypeidExpression</a>.
+ */
+class TypeInfo
+{
+    override hash_t toHash()
+    {
+        hash_t hash;
+
+        foreach (char c; this.toString())
+            hash = hash * 9 + c;
+        return hash;
+    }
+
+    override int opCmp(Object o)
+    {
+        if (this is o)
+            return 0;
+        TypeInfo ti = cast(TypeInfo)o;
+        if (ti is null)
+            return 1;
+        return dstrcmp(this.toString(), ti.toString());
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        /* TypeInfo instances are singletons, but duplicates can exist
+         * across DLL's. Therefore, comparing for a name match is
+         * sufficient.
+         */
+        if (this is o)
+            return true;
+        TypeInfo ti = cast(TypeInfo)o;
+        return ti && this.toString() == ti.toString();
+    }
+
+    /// Returns a hash of the instance of a type.
+    hash_t getHash(in void* p) { return cast(hash_t)p; }
+
+    /// Compares two instances for equality.
+    equals_t equals(in void* p1, in void* p2) { return p1 == p2; }
+
+    /// Compares two instances for &lt;, ==, or &gt;.
+    int compare(in void* p1, in void* p2) { return 0; }
+
+    /// Returns size of the type.
+    size_t tsize() { return 0; }
+
+    /// Swaps two instances of the type.
+    void swap(void* p1, void* p2)
+    {
+        size_t n = tsize();
+        for (size_t i = 0; i < n; i++)
+        {
+            byte t = (cast(byte *)p1)[i];
+            (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
+            (cast(byte*)p2)[i] = t;
+        }
+    }
+
+    /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
+    /// null if none.
+    TypeInfo next() { return null; }
+
+    /// Return default initializer, null if default initialize to 0
+    void[] init() { return null; }
+
+    /// Get flags for type: 1 means GC should scan for pointers
+    uint flags() { return 0; }
+
+    /// Get type information on the contents of the type; null if not available
+    OffsetTypeInfo[] offTi() { return null; }
+    /// Run the destructor on the object and all its sub-objects
+    void destroy(void* p) {}
+    /// Run the postblit on the object and all its sub-objects
+    void postblit(void* p) {}
+}
+
+class TypeInfo_Typedef : TypeInfo
+{
+    override string toString() { return name; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Typedef c;
+        return this is o ||
+               ((c = cast(TypeInfo_Typedef)o) !is null &&
+                this.name == c.name &&
+                this.base == c.base);
+    }
+
+    override hash_t getHash(in void* p) { return base.getHash(p); }
+    override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); }
+    override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); }
+    override size_t tsize() { return base.tsize(); }
+    override void swap(void* p1, void* p2) { return base.swap(p1, p2); }
+
+    override TypeInfo next() { return base.next(); }
+    override uint flags() { return base.flags(); }
+    override void[] init() { return m_init.length ? m_init : base.init(); }
+
+    TypeInfo base;
+    string   name;
+    void[]   m_init;
+}
+
+class TypeInfo_Enum : TypeInfo_Typedef
+{
+
+}
+
+class TypeInfo_Pointer : TypeInfo
+{
+    override string toString() { return m_next.toString() ~ "*"; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Pointer c;
+        return this is o ||
+                ((c = cast(TypeInfo_Pointer)o) !is null &&
+                 this.m_next == c.m_next);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        return cast(hash_t)*cast(void**)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(void**)p1 == *cast(void**)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        if (*cast(void**)p1 < *cast(void**)p2)
+            return -1;
+        else if (*cast(void**)p1 > *cast(void**)p2)
+            return 1;
+        else
+            return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (void*).sizeof;
+    }
+
+    override void swap(void* p1, void* p2)
+    {
+        void* tmp = *cast(void**)p1;
+        *cast(void**)p1 = *cast(void**)p2;
+        *cast(void**)p2 = tmp;
+    }
+
+    override TypeInfo next() { return m_next; }
+    override uint flags() { return 1; }
+
+    TypeInfo m_next;
+}
+
+class TypeInfo_Array : TypeInfo
+{
+    override string toString() { return value.toString() ~ "[]"; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Array c;
+        return this is o ||
+               ((c = cast(TypeInfo_Array)o) !is null &&
+                this.value == c.value);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        size_t sz = value.tsize();
+        hash_t hash = 0;
+        void[] a = *cast(void[]*)p;
+        for (size_t i = 0; i < a.length; i++)
+            hash += value.getHash(a.ptr + i * sz) * 11;
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        void[] a1 = *cast(void[]*)p1;
+        void[] a2 = *cast(void[]*)p2;
+        if (a1.length != a2.length)
+            return false;
+        size_t sz = value.tsize();
+        for (size_t i = 0; i < a1.length; i++)
+        {
+            if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        void[] a1 = *cast(void[]*)p1;
+        void[] a2 = *cast(void[]*)p2;
+        size_t sz = value.tsize();
+        size_t len = a1.length;
+
+        if (a2.length < len)
+            len = a2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
+            if (result)
+                return result;
+        }
+        return cast(int)a1.length - cast(int)a2.length;
+    }
+
+    override size_t tsize()
+    {
+        return (void[]).sizeof;
+    }
+
+    override void swap(void* p1, void* p2)
+    {
+        void[] tmp = *cast(void[]*)p1;
+        *cast(void[]*)p1 = *cast(void[]*)p2;
+        *cast(void[]*)p2 = tmp;
+    }
+
+    TypeInfo value;
+
+    override TypeInfo next()
+    {
+        return value;
+    }
+
+    override uint flags() { return 1; }
+}
+
+class TypeInfo_StaticArray : TypeInfo
+{
+    override string toString()
+    {
+        char[10] tmp = void;
+        return cast(string)(value.toString() ~ "[" ~ tmp.intToString(len) ~ "]");
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_StaticArray c;
+        return this is o ||
+               ((c = cast(TypeInfo_StaticArray)o) !is null &&
+                this.len == c.len &&
+                this.value == c.value);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        size_t sz = value.tsize();
+        hash_t hash = 0;
+        for (size_t i = 0; i < len; i++)
+            hash += value.getHash(p + i * sz);
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        size_t sz = value.tsize();
+
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!value.equals(p1 + u * sz, p2 + u * sz))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        size_t sz = value.tsize();
+
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = value.compare(p1 + u * sz, p2 + u * sz);
+            if (result)
+                return result;
+        }
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return len * value.tsize();
+    }
+
+    override void swap(void* p1, void* p2)
+    {
+        void* tmp;
+        size_t sz = value.tsize();
+        ubyte[16] buffer;
+        void* pbuffer;
+
+        if (sz < buffer.sizeof)
+            tmp = buffer.ptr;
+        else
+            tmp = pbuffer = (new void[sz]).ptr;
+
+        for (size_t u = 0; u < len; u += sz)
+        {   size_t o = u * sz;
+            memcpy(tmp, p1 + o, sz);
+            memcpy(p1 + o, p2 + o, sz);
+            memcpy(p2 + o, tmp, sz);
+        }
+        if (pbuffer)
+            delete pbuffer;
+    }
+
+    override void[] init() { return value.init(); }
+    override TypeInfo next() { return value; }
+    override uint flags() { return value.flags(); }
+
+    override void destroy(void* p)
+    {
+        auto sz = value.tsize();
+        p += sz * len;
+        foreach (i; 0 .. len)
+        {
+            p -= sz;
+            value.destroy(p);
+        }
+    }
+
+    override void postblit(void* p)
+    {
+        auto sz = value.tsize();
+        foreach (i; 0 .. len)
+        {
+            value.postblit(p);
+            p += sz;
+        }
+    }
+
+    TypeInfo value;
+    size_t   len;
+}
+
+class TypeInfo_AssociativeArray : TypeInfo
+{
+    override string toString()
+    {
+        return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]");
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_AssociativeArray c;
+        return this is o ||
+                ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
+                 this.key == c.key &&
+                 this.value == c.value);
+    }
+
+    // BUG: need to add the rest of the functions
+
+    override size_t tsize()
+    {
+        return (char[int]).sizeof;
+    }
+
+    override TypeInfo next() { return value; }
+    override uint flags() { return 1; }
+
+    TypeInfo value;
+    TypeInfo key;
+}
+
+class TypeInfo_Function : TypeInfo
+{
+    override string toString()
+    {
+        return cast(string)(next.toString() ~ "()");
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Function c;
+        return this is o ||
+                ((c = cast(TypeInfo_Function)o) !is null &&
+                 this.next == c.next);
+    }
+
+    // BUG: need to add the rest of the functions
+
+    override size_t tsize()
+    {
+        return 0;       // no size for functions
+    }
+
+    TypeInfo next;
+}
+
+class TypeInfo_Delegate : TypeInfo
+{
+    override string toString()
+    {
+        return cast(string)(next.toString() ~ " delegate()");
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Delegate c;
+        return this is o ||
+                ((c = cast(TypeInfo_Delegate)o) !is null &&
+                 this.next == c.next);
+    }
+
+    // BUG: need to add the rest of the functions
+
+    override size_t tsize()
+    {
+        alias int delegate() dg;
+        return dg.sizeof;
+    }
+
+    override uint flags() { return 1; }
+
+    TypeInfo next;
+}
+
+class TypeInfo_Class : TypeInfo
+{
+    override string toString() { return info.name; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Class c;
+        return this is o ||
+                ((c = cast(TypeInfo_Class)o) !is null &&
+                 this.info.name == c.classinfo.name);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        Object o = *cast(Object*)p;
+        return o ? o.toHash() : 0;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        Object o1 = *cast(Object*)p1;
+        Object o2 = *cast(Object*)p2;
+
+        return (o1 is o2) || (o1 && o1.opEquals(o2));
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        Object o1 = *cast(Object*)p1;
+        Object o2 = *cast(Object*)p2;
+        int c = 0;
+
+        // Regard null references as always being "less than"
+        if (o1 !is o2)
+        {
+            if (o1)
+            {
+                if (!o2)
+                    c = 1;
+                else
+                    c = o1.opCmp(o2);
+            }
+            else
+                c = -1;
+        }
+        return c;
+    }
+
+    override size_t tsize()
+    {
+        return Object.sizeof;
+    }
+
+    override uint flags() { return 1; }
+
+    override OffsetTypeInfo[] offTi()
+    {
+        return (info.flags & 4) ? info.offTi : null;
+    }
+
+    ClassInfo info;
+}
+
+class TypeInfo_Interface : TypeInfo
+{
+    override string toString() { return info.name; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Interface c;
+        return this is o ||
+                ((c = cast(TypeInfo_Interface)o) !is null &&
+                 this.info.name == c.classinfo.name);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        Interface* pi = **cast(Interface ***)*cast(void**)p;
+        Object o = cast(Object)(*cast(void**)p - pi.offset);
+        assert(o);
+        return o.toHash();
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        Interface* pi = **cast(Interface ***)*cast(void**)p1;
+        Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
+        pi = **cast(Interface ***)*cast(void**)p2;
+        Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
+
+        return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        Interface* pi = **cast(Interface ***)*cast(void**)p1;
+        Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
+        pi = **cast(Interface ***)*cast(void**)p2;
+        Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
+        int c = 0;
+
+        // Regard null references as always being "less than"
+        if (o1 != o2)
+        {
+            if (o1)
+            {
+                if (!o2)
+                    c = 1;
+                else
+                    c = o1.opCmp(o2);
+            }
+            else
+                c = -1;
+        }
+        return c;
+    }
+
+    override size_t tsize()
+    {
+        return Object.sizeof;
+    }
+
+    override uint flags() { return 1; }
+
+    ClassInfo info;
+}
+
+class TypeInfo_Struct : TypeInfo
+{
+    override string toString() { return name; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Struct s;
+        return this is o ||
+                ((s = cast(TypeInfo_Struct)o) !is null &&
+                 this.name == s.name &&
+                 this.init.length == s.init.length);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        assert(p);
+        if (xtoHash)
+        {
+            debug(PRINTF) printf("getHash() using xtoHash\n");
+            return (*xtoHash)(p);
+        }
+        else
+        {
+            hash_t h;
+            debug(PRINTF) printf("getHash() using default hash\n");
+            // A sorry hash algorithm.
+            // Should use the one for strings.
+            // BUG: relies on the GC not moving objects
+            auto q = cast(const(ubyte)*)p;
+            for (size_t i = 0; i < init.length; i++)
+            {
+                h = h * 9 + *q;
+                q++;
+            }
+            return h;
+        }
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        if (p1 == p2)
+            return true;
+        else if (!p1 || !p2)
+            return false;
+        else if (xopEquals)
+            return (*xopEquals)(p1, p2);
+        else
+            // BUG: relies on the GC not moving objects
+            return memcmp(p1, p2, init.length) == 0;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        // Regard null references as always being "less than"
+        if (p1 != p2)
+        {
+            if (p1)
+            {
+                if (!p2)
+                    return true;
+                else if (xopCmp)
+                    return (*xopCmp)(p2, p1);
+                else
+                    // BUG: relies on the GC not moving objects
+                    return memcmp(p1, p2, init.length);
+            }
+            else
+                return -1;
+        }
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return init.length;
+    }
+
+    override void[] init() { return m_init; }
+
+    override uint flags() { return m_flags; }
+
+    override void destroy(void* p)
+    {
+        if (xdtor)
+            (*xdtor)(p);
+    }
+
+    override void postblit(void* p)
+    {
+        if (xpostblit)
+            (*xpostblit)(p);
+    }
+
+    string name;
+    void[] m_init;      // initializer; init.ptr == null if 0 initialize
+
+    hash_t   function(in void*)           xtoHash;
+    equals_t function(in void*, in void*) xopEquals;
+    int      function(in void*, in void*) xopCmp;
+    char[]   function(in void*)           xtoString;
+
+    uint m_flags;
+
+    const(MemberInfo[]) function(in char[]) xgetMembers;
+    void function(void*)                    xdtor;
+    void function(void*)                    xpostblit;
+}
+
+class TypeInfo_Tuple : TypeInfo
+{
+    TypeInfo[] elements;
+
+    override string toString()
+    {
+        string s = "(";
+        foreach (i, element; elements)
+        {
+            if (i)
+                s ~= ',';
+            s ~= element.toString();
+        }
+        s ~= ")";
+        return s;
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        if (this is o)
+            return true;
+
+        auto t = cast(TypeInfo_Tuple)o;
+        if (t && elements.length == t.elements.length)
+        {
+            for (size_t i = 0; i < elements.length; i++)
+            {
+                if (elements[i] != t.elements[i])
+                    return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        assert(0);
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        assert(0);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        assert(0);
+    }
+
+    override size_t tsize()
+    {
+        assert(0);
+    }
+
+    override void swap(void* p1, void* p2)
+    {
+        assert(0);
+    }
+
+    override void destroy(void* p)
+    {
+        assert(0);
+    }
+
+    override void postblit(void* p)
+    {
+        assert(0);
+    }
+}
+
+class TypeInfo_Const : TypeInfo
+{
+    override string toString()
+    {
+        return cast(string) ("const(" ~ base.toString() ~ ")");
+    }
+
+    override equals_t opEquals(Object o) { return base.opEquals(o); }
+    override hash_t getHash(in void *p) { return base.getHash(p); }
+    override equals_t equals(in void *p1, in void *p2) { return base.equals(p1, p2); }
+    override int compare(in void *p1, in void *p2) { return base.compare(p1, p2); }
+    override size_t tsize() { return base.tsize(); }
+    override void swap(void *p1, void *p2) { return base.swap(p1, p2); }
+
+    override TypeInfo next() { return base.next(); }
+    override uint flags() { return base.flags(); }
+    override void[] init() { return base.init(); }
+
+    TypeInfo base;
+}
+
+class TypeInfo_Invariant : TypeInfo_Const
+{
+    override string toString()
+    {
+        return cast(string) ("immutable(" ~ base.toString() ~ ")");
+    }
+}
+
+class TypeInfo_Shared : TypeInfo_Const
+{
+    override string toString()
+    {
+        return cast(string) ("shared(" ~ base.toString() ~ ")");
+    }
+}
+
+abstract class MemberInfo
+{
+    string name();
+}
+
+class MemberInfo_field : MemberInfo
+{
+    this(string name, TypeInfo ti, size_t offset)
+    {
+        m_name = name;
+        m_typeinfo = ti;
+        m_offset = offset;
+    }
+
+    override string name() { return m_name; }
+    TypeInfo typeInfo() { return m_typeinfo; }
+    size_t offset() { return m_offset; }
+
+    string   m_name;
+    TypeInfo m_typeinfo;
+    size_t   m_offset;
+}
+
+class MemberInfo_function : MemberInfo
+{
+    this(string name, TypeInfo ti, void* fp, uint flags)
+    {
+        m_name = name;
+        m_typeinfo = ti;
+        m_fp = fp;
+        m_flags = flags;
+    }
+
+    override string name() { return m_name; }
+    TypeInfo typeInfo() { return m_typeinfo; }
+    void* fp() { return m_fp; }
+    uint flags() { return m_flags; }
+
+    string   m_name;
+    TypeInfo m_typeinfo;
+    void*    m_fp;
+    uint     m_flags;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Throwable
+///////////////////////////////////////////////////////////////////////////////
+
+
+class Throwable : Object
+{
+    interface TraceInfo
+    {
+        int opApply(int delegate(inout char[]));
+    }
+
+    string      msg;
+    string      file;
+    size_t      line;
+    TraceInfo   info;
+    Throwable   next;
+
+    this(string msg, Throwable next = null)
+    {
+        this.msg = msg;
+        this.next = next;
+        this.info = traceContext();
+    }
+
+    this(string msg, string file, size_t line, Throwable next = null)
+    {
+        this(msg, next);
+        this.file = file;
+        this.line = line;
+        this.info = traceContext();
+    }
+
+    override string toString()
+    {
+        char[10] tmp = void;
+        char[]   buf;
+
+        for (Throwable e = this; e !is null; e = e.next)
+        {
+            if (e.file)
+            {
+               buf ~= e.classinfo.name ~ "@" ~ e.file ~ "(" ~ tmp.intToString(e.line) ~ "): " ~ e.msg;
+            }
+            else
+            {
+               buf ~= e.classinfo.name ~ ": " ~ e.msg;
+            }
+            if (e.info)
+            {
+                buf ~= "\n----------------";
+                foreach (t; e.info)
+                    buf ~= "\n" ~ t;
+            }
+            if (e.next)
+                buf ~= "\n";
+        }
+        return cast(string) buf;
+    }
+}
+
+
+alias Throwable.TraceInfo function(void* ptr = null) TraceHandler;
+private __gshared TraceHandler traceHandler = null;
+
+
+/**
+ * Overrides the default trace hander with a user-supplied version.
+ *
+ * Params:
+ *  h = The new trace handler.  Set to null to use the default handler.
+ */
+extern (C) void  rt_setTraceHandler(TraceHandler h)
+{
+    traceHandler = h;
+}
+
+
+/**
+ * This function will be called when an exception is constructed.  The
+ * user-supplied trace handler will be called if one has been supplied,
+ * otherwise no trace will be generated.
+ *
+ * Params:
+ *  ptr = A pointer to the location from which to generate the trace, or null
+ *        if the trace should be generated from within the trace handler
+ *        itself.
+ *
+ * Returns:
+ *  An object describing the current calling context or null if no handler is
+ *  supplied.
+ */
+Throwable.TraceInfo traceContext(void* ptr = null)
+{
+    if (traceHandler is null)
+        return null;
+    return traceHandler(ptr);
+}
+
+
+class Exception : Throwable
+{
+    this(string msg, Throwable next = null)
+    {
+        super(msg, next);
+    }
+
+    this(string msg, string file, size_t line, Throwable next = null)
+    {
+        super(msg, file, line, next);
+    }
+}
+
+
+class Error : Throwable
+{
+    this(string msg, Throwable next = null)
+    {
+        super(msg, next);
+    }
+
+    this(string msg, string file, size_t line, Throwable next = null)
+    {
+        super(msg, file, line, next);
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// ModuleInfo
+///////////////////////////////////////////////////////////////////////////////
+
+
+enum
+{
+    MIctorstart  = 1,   // we've started constructing it
+    MIctordone   = 2,   // finished construction
+    MIstandalone = 4,   // module ctor does not depend on other module
+                        // ctors being done first
+    MIhasictor   = 8,   // has ictor member
+}
+
+
+class ModuleInfo
+{
+    string          name;
+    ModuleInfo[]    importedModules;
+    ClassInfo[]     localClasses;
+    uint            flags;
+
+    void function() ctor;       // module static constructor (order dependent)
+    void function() dtor;       // module static destructor
+    void function() unitTest;   // module unit tests
+
+    void* xgetMembers;          // module getMembers() function
+
+    void function() ictor;      // module static constructor (order independent)
+
+    void*[4] reserved;		// for future expansion
+
+    static int opApply(int delegate(inout ModuleInfo) dg)
+    {
+        int ret = 0;
+
+        foreach (m; _moduleinfo_array)
+        {
+            ret = dg(m);
+            if (ret)
+                break;
+        }
+        return ret;
+    }
+}
+
+
+// Windows: this gets initialized by minit.asm
+// Posix: this gets initialized in _moduleCtor()
+extern (C) __gshared ModuleInfo[] _moduleinfo_array;
+
+
+version (linux)
+{
+    // This linked list is created by a compiler generated function inserted
+    // into the .ctor list by the compiler.
+    struct ModuleReference
+    {
+        ModuleReference* next;
+        ModuleInfo       mod;
+    }
+
+    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
+}
+
+version (FreeBSD)
+{
+    // This linked list is created by a compiler generated function inserted
+    // into the .ctor list by the compiler.
+    struct ModuleReference
+    {
+        ModuleReference* next;
+        ModuleInfo       mod;
+    }
+
+    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
+}
+
+version (Solaris)
+{
+    // This linked list is created by a compiler generated function inserted
+    // into the .ctor list by the compiler.
+    struct ModuleReference
+    {
+        ModuleReference* next;
+        ModuleInfo       mod;
+    }
+
+    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
+}
+
+version (OSX)
+{
+    extern (C)
+    {
+        extern __gshared void* _minfo_beg;
+        extern __gshared void* _minfo_end;
+    }
+}
+
+__gshared ModuleInfo[] _moduleinfo_dtors;
+__gshared uint         _moduleinfo_dtors_i;
+
+// Register termination function pointers
+extern (C) int _fatexit(void*);
+
+/**
+ * Initialize the modules.
+ */
+
+extern (C) void _moduleCtor()
+{
+    debug(PRINTF) printf("_moduleCtor()\n");
+    version (linux)
+    {
+        int len = 0;
+        ModuleReference *mr;
+
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+            len++;
+        _moduleinfo_array = new ModuleInfo[len];
+        len = 0;
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+        {   _moduleinfo_array[len] = mr.mod;
+            len++;
+        }
+    }
+
+    version (FreeBSD)
+    {
+        int len = 0;
+        ModuleReference *mr;
+
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+            len++;
+        _moduleinfo_array = new ModuleInfo[len];
+        len = 0;
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+        {   _moduleinfo_array[len] = mr.mod;
+            len++;
+        }
+    }
+
+    version (Solaris)
+    {
+        int len = 0;
+        ModuleReference *mr;
+
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+            len++;
+        _moduleinfo_array = new ModuleInfo[len];
+        len = 0;
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+        {   _moduleinfo_array[len] = mr.mod;
+            len++;
+        }
+    }
+
+    version (OSX)
+    {
+        /* The ModuleInfo references are stored in the special segment
+         * __minfodata, which is bracketed by the segments __minfo_beg
+         * and __minfo_end. The variables _minfo_beg and _minfo_end
+         * are of zero size and are in the two bracketing segments,
+         * respectively.
+         */
+         size_t length = cast(ModuleInfo*)&_minfo_end - cast(ModuleInfo*)&_minfo_beg;
+         _moduleinfo_array = (cast(ModuleInfo*)&_minfo_beg)[0 .. length];
+         debug printf("moduleinfo: ptr = %p, length = %d\n", _moduleinfo_array.ptr, _moduleinfo_array.length);
+
+         debug foreach (m; _moduleinfo_array)
+         {
+             //printf("\t%p\n", m);
+             printf("\t%.*s\n", m.name);
+         }
+    }    
+
+    version (Windows)
+    {
+        // Ensure module destructors also get called on program termination
+        //_fatexit(&_STD_moduleDtor);
+    }
+
+    _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
+    debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors);
+    _moduleIndependentCtors();
+    _moduleCtor2(_moduleinfo_array, 0);
+}
+
+extern (C) void _moduleIndependentCtors()
+{
+    debug(PRINTF) printf("_moduleIndependentCtors()\n");
+    foreach (m; _moduleinfo_array)
+    {
+        if (m && m.flags & MIhasictor && m.ictor)
+        {
+            (*m.ictor)();
+        }
+    }
+}
+
+void _moduleCtor2(ModuleInfo[] mi, int skip)
+{
+    debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
+    for (uint i = 0; i < mi.length; i++)
+    {
+        ModuleInfo m = mi[i];
+
+        debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
+        if (!m)
+            continue;
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
+        if (m.flags & MIctordone)
+            continue;
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
+
+        if (m.ctor || m.dtor)
+        {
+            if (m.flags & MIctorstart)
+            {   if (skip || m.flags & MIstandalone)
+                    continue;
+                    throw new Exception("Cyclic dependency in module " ~ m.name);
+            }
+
+            m.flags |= MIctorstart;
+            _moduleCtor2(m.importedModules, 0);
+            if (m.ctor)
+                (*m.ctor)();
+            m.flags &= ~MIctorstart;
+            m.flags |= MIctordone;
+
+            // Now that construction is done, register the destructor
+            //printf("\tadding module dtor x%x\n", m);
+            assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
+            _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
+        }
+        else
+        {
+            m.flags |= MIctordone;
+            _moduleCtor2(m.importedModules, 1);
+        }
+    }
+}
+
+/**
+ * Destruct the modules.
+ */
+
+// Starting the name with "_STD" means under Posix a pointer to the
+// function gets put in the .dtors segment.
+
+extern (C) void _moduleDtor()
+{
+    debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
+
+    for (uint i = _moduleinfo_dtors_i; i-- != 0;)
+    {
+        ModuleInfo m = _moduleinfo_dtors[i];
+
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
+        if (m.dtor)
+        {
+            (*m.dtor)();
+        }
+    }
+    debug(PRINTF) printf("_moduleDtor() done\n");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Monitor
+///////////////////////////////////////////////////////////////////////////////
+
+alias Object.Monitor        IMonitor;
+alias void delegate(Object) DEvent;
+
+// NOTE: The dtor callback feature is only supported for monitors that are not
+//       supplied by the user.  The assumption is that any object with a user-
+//       supplied monitor may have special storage or lifetime requirements and
+//       that as a result, storing references to local objects within Monitor
+//       may not be safe or desirable.  Thus, devt is only valid if impl is
+//       null.
+struct Monitor
+{
+    IMonitor impl;
+    /* internal */
+    DEvent[] devt;
+    /* stuff */
+}
+
+Monitor* getMonitor(Object h)
+{
+    return cast(Monitor*) (cast(void**) h)[1];
+}
+
+void setMonitor(Object h, Monitor* m)
+{
+    (cast(void**) h)[1] = m;
+}
+
+extern (C) void _d_monitor_create(Object);
+extern (C) void _d_monitor_destroy(Object);
+extern (C) void _d_monitor_lock(Object);
+extern (C) int  _d_monitor_unlock(Object);
+
+extern (C) void _d_monitordelete(Object h, bool det)
+{
+    Monitor* m = getMonitor(h);
+
+    if (m !is null)
+    {
+        IMonitor i = m.impl;
+        if (i is null)
+        {
+            _d_monitor_devt(m, h);
+            _d_monitor_destroy(h);
+            setMonitor(h, null);
+            return;
+        }
+        if (det && (cast(void*) i) !is (cast(void*) h))
+            delete i;
+        setMonitor(h, null);
+    }
+}
+
+extern (C) void _d_monitorenter(Object h)
+{
+    Monitor* m = getMonitor(h);
+
+    if (m is null)
+    {
+        _d_monitor_create(h);
+        m = getMonitor(h);
+    }
+
+    IMonitor i = m.impl;
+
+    if (i is null)
+    {
+        _d_monitor_lock(h);
+        return;
+    }
+    i.lock();
+}
+
+extern (C) void _d_monitorexit(Object h)
+{
+    Monitor* m = getMonitor(h);
+    IMonitor i = m.impl;
+
+    if (i is null)
+    {
+        _d_monitor_unlock(h);
+        return;
+    }
+    i.unlock();
+}
+
+extern (C) void _d_monitor_devt(Monitor* m, Object h)
+{
+    if (m.devt.length)
+    {
+        DEvent[] devt;
+
+        synchronized (h)
+        {
+            devt = m.devt;
+            m.devt = null;
+        }
+        foreach (v; devt)
+        {
+            if (v)
+                v(h);
+        }
+        free(devt.ptr);
+    }
+}
+
+extern (C) void rt_attachDisposeEvent(Object h, DEvent e)
+{
+    synchronized (h)
+    {
+        Monitor* m = getMonitor(h);
+        assert(m.impl is null);
+
+        foreach (inout v; m.devt)
+        {
+            if (v is null || v == e)
+            {
+                v = e;
+                return;
+            }
+        }
+
+        auto len = m.devt.length + 4; // grow by 4 elements
+        auto pos = m.devt.length;     // insert position
+        auto p = realloc(m.devt.ptr, DEvent.sizeof * len);
+        if (!p)
+            onOutOfMemoryError();
+        m.devt = (cast(DEvent*)p)[0 .. len];
+        m.devt[pos+1 .. len] = null;
+        m.devt[pos] = e;
+    }
+}
+
+extern (C) void rt_detachDisposeEvent(Object h, DEvent e)
+{
+    synchronized (h)
+    {
+        Monitor* m = getMonitor(h);
+        assert(m.impl is null);
+
+        foreach (p, v; m.devt)
+        {
+            if (v == e)
+            {
+                memmove(&m.devt[p],
+                        &m.devt[p+1],
+                        (m.devt.length - p - 1) * DEvent.sizeof);
+                m.devt[$ - 1] = null;
+                return;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/posix.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,82 @@
+# Makefile to build the compiler runtime D library for Linux
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR=../../../lib
+DOCDIR=../../../doc
+IMPDIR=../../../import
+LIBBASENAME=libdruntime-rt-dmd.a
+MODULES=
+BUILDS=debug release unittest
+
+MODULES_BASE=aaA aApply aApplyR adi alloca arrayassign arraybyte	\
+    arraycast arraycat arraydouble arrayfloat arrayint arrayreal	\
+    arrayshort cast_ cmath2 cover deh2 dmain2 invariant invariant_	\
+    lifetime llmath memory memset obj object_ qsort switch_ trace
+# NOTE: trace.o and cover.o are not necessary for a successful build
+#       as both are used for debugging features (profiling and coverage)
+# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and
+#       minit.asm is not used by dmd for Linux
+# NOTE: deh.o is only needed for Win32, Linux uses deh2.o
+MODULES_UTIL=$(addprefix util/,console cpuid ctype string utf)
+MODULES_TI=$(addprefix typeinfo/ti_,AC Acdouble Acfloat Acreal Adouble	\
+    Afloat Ag Aint Along Areal Ashort byte C cdouble cfloat char creal	\
+    dchar delegate double float idouble ifloat int ireal long ptr real	\
+    short ubyte uint ulong ushort void wchar)
+C_SRCS=complex.c critical.c memory_osx.c monitor.c
+
+# Symbols
+
+DMD=dmd
+DOCFLAGS=-version=DDoc
+DFLAGS_release=-d -release -O -inline -w -nofloat
+DFLAGS_debug=-d -g -w -nofloat
+DFLAGS_unittest=$(DFLAGS_release) -unittest
+CFLAGS_release=-m32 -O
+CFLAGS_debug=-m32 -g
+CFLAGS_unittest=$(CFLAGS_release)
+
+# Derived symbols
+
+C_OBJS=$(addsuffix .o,$(basename $(C_SRCS)))
+AS_OBJS=$(addsuffix .o,$(basename $(AS_SRCS)))
+ALL_MODULES=$(MODULES_BASE) $(MODULES_UTIL) $(MODULES_TI)
+D_SRCS=$(addsuffix .d,$(ALL_MODULES))
+ALLLIBS=$(addsuffix /$(LIBBASENAME),$(addprefix $(LIBDIR)/,$(BUILDS)))
+
+# Patterns
+
+$(LIBDIR)/%/$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_SRCS)
+	$(CC) -c $(CFLAGS_$*) $(C_SRCS)
+	$(DMD) $(DFLAGS_$*) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS)
+	rm $(C_OBJS) $(AS_OBJS)
+
+$(DOCDIR)/%.html : %.d
+	$(DMD) -c -d -o- -Df$@ $<
+
+$(IMPDIR)/%.di : %.d
+	$(DMD) -c -d -o- -Hf$@ $<
+
+# Rulez
+
+all : $(BUILDS) doc
+
+debug : $(LIBDIR)/debug/$(LIBBASENAME) $(IMPORTS)
+release : $(LIBDIR)/release/$(LIBBASENAME) $(IMPORTS)
+unittest : $(LIBDIR)/unittest/$(LIBBASENAME) $(IMPORTS)
+#doc : $(DOCS)
+
+clean :
+	rm -f $(IMPORTS) $(DOCS) $(ALLLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/qsort.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,158 @@
+/*
+        Portions of this file are:
+        Copyright Prototronics, 1987
+        Totem Lake P.O. 8117
+        Kirkland, Washington 98034
+        (206) 820-1972
+        Licensed to Digital Mars.
+
+        June 11, 1987 from Ray Gardner's
+        Denver, Colorado) public domain version
+
+        Use qsort2.d instead of this file if a redistributable version of
+        _adSort() is required.
+*/
+
+module rt.qsort;
+
+/*
+**    Sorts an array starting at base, of length nbr_elements, each
+**    element of size width_bytes, ordered via compare_function; which
+**    is called as  (*comp_fp)(ptr_to_element1, ptr_to_element2)
+**    and returns < 0 if element1 < element2, 0 if element1 = element2,
+**    > 0 if element1 > element2.  Most of the refinements are due to
+**    R. Sedgewick.  See "Implementing Quicksort Programs", Comm. ACM,
+**    Oct. 1978, and Corrigendum, Comm. ACM, June 1979.
+*/
+
+//debug=qsort;          // uncomment to turn on debugging printf's
+
+
+struct Array
+{
+    size_t length;
+    void*  ptr;
+}
+
+
+private const int _maxspan = 7; // subarrays of _maxspan or fewer elements
+                                // will be sorted by a simple insertion sort
+
+/* Adjust _maxspan according to relative cost of a swap and a compare.  Reduce
+_maxspan (not less than 1) if a swap is very expensive such as when you have
+an array of large structures to be sorted, rather than an array of pointers to
+structures.  The default value is optimized for a high cost for compares. */
+
+
+extern (C) long _adSort(Array a, TypeInfo ti)
+{
+  byte* base;
+  byte*[40] stack;              // stack
+  byte** sp;                    // stack pointer
+  byte* i, j, limit;            // scan and limit pointers
+  uint thresh;                  // size of _maxspan elements in bytes
+  uint width = ti.tsize();
+
+  base = cast(byte *)a.ptr;
+  thresh = _maxspan * width;             // init threshold
+  sp = stack.ptr;                        // init stack pointer
+  limit = base + a.length * width;       // pointer past end of array
+  while (1)                              // repeat until done then return
+  {
+    while (limit - base > thresh)        // if more than _maxspan elements
+    {
+      //swap middle, base
+      ti.swap((cast(uint)(limit - base) >> 1) -
+           (((cast(uint)(limit - base) >> 1)) % width) + base, base);
+
+      i = base + width;                 // i scans from left to right
+      j = limit - width;                // j scans from right to left
+
+      if (ti.compare(i, j) > 0)         // Sedgewick's
+        ti.swap(i, j);                  //    three-element sort
+      if (ti.compare(base, j) > 0)      // sets things up
+        ti.swap(base, j);               // so that
+      if (ti.compare(i, base) > 0)      // *i <= *base <= *j
+        ti.swap(i, base);               // *base is the pivot element
+
+      while (1)
+      {
+        do                              // move i right until *i >= pivot
+          i += width;
+        while (ti.compare(i, base) < 0);
+        do                              // move j left until *j <= pivot
+          j -= width;
+        while (ti.compare(j, base) > 0);
+        if (i > j)                      // break loop if pointers crossed
+          break;
+        ti.swap(i, j);                  // else swap elements, keep scanning
+      }
+      ti.swap(base, j);                 // move pivot into correct place
+      if (j - base > limit - i)         // if left subarray is larger...
+      {
+        sp[0] = base;                   // stack left subarray base
+        sp[1] = j;                      //    and limit
+        base = i;                       // sort the right subarray
+      }
+      else                              // else right subarray is larger
+      {
+        sp[0] = i;                      // stack right subarray base
+        sp[1] = limit;                  //    and limit
+        limit = j;                      // sort the left subarray
+      }
+      sp += 2;                          // increment stack pointer
+      assert(sp < cast(byte**)stack + stack.length);
+    }
+
+    // Insertion sort on remaining subarray
+    i = base + width;
+    while (i < limit)
+    {
+      j = i;
+      while (j > base && ti.compare(j - width, j) > 0)
+      {
+        ti.swap(j - width, j);
+        j -= width;
+      }
+      i += width;
+    }
+
+    if (sp > stack.ptr)                 // if any entries on stack...
+    {
+      sp -= 2;                          // pop the base and limit
+      base = sp[0];
+      limit = sp[1];
+    }
+    else                                // else stack empty, all done
+      return *cast(long*)(&a);
+  }
+  assert(0);
+}
+
+
+unittest
+{
+    debug(qsort) printf("array.sort.unittest()\n");
+
+    int a[] = new int[10];
+
+    a[0] = 23;
+    a[1] = 1;
+    a[2] = 64;
+    a[3] = 5;
+    a[4] = 6;
+    a[5] = 5;
+    a[6] = 17;
+    a[7] = 3;
+    a[8] = 0;
+    a[9] = -1;
+
+    a.sort;
+
+    for (int i = 0; i < a.length - 1; i++)
+    {
+        //printf("i = %d", i);
+        //printf(" %d %d\n", a[i], a[i + 1]);
+        assert(a[i] <= a[i + 1]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/qsort2.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,71 @@
+/**
+ * This is a public domain version of qsort.d.  All it does is call C's
+ * qsort(), but runs a little slower since it needs to synchronize a global
+ * variable.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.qsort2;
+
+//debug=qsort;
+
+private import core.stdc.stdlib;
+
+struct Array
+{
+    size_t length;
+    void*  ptr;
+}
+
+private TypeInfo tiglobal;
+
+extern (C) int cmp(void* p1, void* p2)
+{
+    return tiglobal.compare(p1, p2);
+}
+
+extern (C) long _adSort(Array a, TypeInfo ti)
+{
+    synchronized
+    {
+        tiglobal = ti;
+        qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp);
+    }
+    return *cast(long*)(&a);
+}
+
+
+
+unittest
+{
+    debug(qsort) printf("array.sort.unittest()\n");
+
+    int a[] = new int[10];
+
+    a[0] = 23;
+    a[1] = 1;
+    a[2] = 64;
+    a[3] = 5;
+    a[4] = 6;
+    a[5] = 5;
+    a[6] = 17;
+    a[7] = 3;
+    a[8] = 0;
+    a[9] = -1;
+
+    a.sort;
+
+    for (int i = 0; i < a.length - 1; i++)
+    {
+        //printf("i = %d", i);
+        //printf(" %d %d\n", a[i], a[i + 1]);
+        assert(a[i] <= a[i + 1]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/switch_.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,411 @@
+/**
+ * Contains support code for switch blocks using string constants.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.switch_;
+
+private import core.stdc.string;
+
+/******************************************************
+ * Support for switch statements switching on strings.
+ * Input:
+ *      table[]         sorted array of strings generated by compiler
+ *      ca              string to look up in table
+ * Output:
+ *      result          index of match in table[]
+ *                      -1 if not in table
+ */
+
+extern (C):
+
+int _d_switch_string(char[][] table, char[] ca)
+in
+{
+    //printf("in _d_switch_string()\n");
+    assert(table.length >= 0);
+    assert(ca.length >= 0);
+
+    // Make sure table[] is sorted correctly
+    int j;
+
+    for (j = 1; j < table.length; j++)
+    {
+        int len1 = table[j - 1].length;
+        int len2 = table[j].length;
+
+        assert(len1 <= len2);
+        if (len1 == len2)
+        {
+            int ci;
+
+            ci = memcmp(table[j - 1].ptr, table[j].ptr, len1);
+            assert(ci < 0); // ci==0 means a duplicate
+        }
+    }
+}
+out (result)
+{
+    int i;
+    int cj;
+
+    //printf("out _d_switch_string()\n");
+    if (result == -1)
+    {
+        // Not found
+        for (i = 0; i < table.length; i++)
+        {
+            if (table[i].length == ca.length)
+            {   cj = memcmp(table[i].ptr, ca.ptr, ca.length);
+                assert(cj != 0);
+            }
+        }
+    }
+    else
+    {
+        assert(0 <= result && result < table.length);
+        for (i = 0; 1; i++)
+        {
+            assert(i < table.length);
+            if (table[i].length == ca.length)
+            {
+                cj = memcmp(table[i].ptr, ca.ptr, ca.length);
+                if (cj == 0)
+                {
+                    assert(i == result);
+                    break;
+                }
+            }
+        }
+    }
+}
+body
+{
+    //printf("body _d_switch_string(%.*s)\n", ca);
+    int low;
+    int high;
+    int mid;
+    int c;
+    char[] pca;
+
+    low = 0;
+    high = table.length;
+
+    version (none)
+    {
+        // Print table
+        printf("ca[] = '%s'\n", cast(char *)ca);
+        for (mid = 0; mid < high; mid++)
+        {
+            pca = table[mid];
+            printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
+        }
+    }
+    if (high &&
+        ca.length >= table[0].length &&
+        ca.length <= table[high - 1].length)
+    {
+        // Looking for 0 length string, which would only be at the beginning
+        if (ca.length == 0)
+            return 0;
+
+        char c1 = ca[0];
+
+        // Do binary search
+        while (low < high)
+        {
+            mid = (low + high) >> 1;
+            pca = table[mid];
+            c = ca.length - pca.length;
+            if (c == 0)
+            {
+                c = cast(ubyte)c1 - cast(ubyte)pca[0];
+                if (c == 0)
+                {
+                    c = memcmp(ca.ptr, pca.ptr, ca.length);
+                    if (c == 0)
+                    {   //printf("found %d\n", mid);
+                        return mid;
+                    }
+                }
+            }
+            if (c < 0)
+            {
+                high = mid;
+            }
+            else
+            {
+                low = mid + 1;
+            }
+        }
+    }
+
+    //printf("not found\n");
+    return -1; // not found
+}
+
+unittest
+{
+    switch (cast(char []) "c")
+    {
+         case "coo":
+         default:
+             break;
+    }
+}
+
+/**********************************
+ * Same thing, but for wide chars.
+ */
+
+int _d_switch_ustring(wchar[][] table, wchar[] ca)
+in
+{
+    //printf("in _d_switch_ustring()\n");
+    assert(table.length >= 0);
+    assert(ca.length >= 0);
+
+    // Make sure table[] is sorted correctly
+    int j;
+
+    for (j = 1; j < table.length; j++)
+    {
+        int len1 = table[j - 1].length;
+        int len2 = table[j].length;
+
+        assert(len1 <= len2);
+        if (len1 == len2)
+        {
+            int c;
+
+            c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof);
+            assert(c < 0);  // c==0 means a duplicate
+        }
+    }
+}
+out (result)
+{
+    int i;
+    int c;
+
+    //printf("out _d_switch_string()\n");
+    if (result == -1)
+    {
+        // Not found
+        for (i = 0; i < table.length; i++)
+        {
+            if (table[i].length == ca.length)
+            {   c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
+                assert(c != 0);
+            }
+        }
+    }
+    else
+    {
+        assert(0 <= result && result < table.length);
+        for (i = 0; 1; i++)
+        {
+            assert(i < table.length);
+            if (table[i].length == ca.length)
+            {
+                c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
+                if (c == 0)
+                {
+                    assert(i == result);
+                    break;
+                }
+            }
+        }
+    }
+}
+body
+{
+    //printf("body _d_switch_ustring()\n");
+    int low;
+    int high;
+    int mid;
+    int c;
+    wchar[] pca;
+
+    low = 0;
+    high = table.length;
+
+/*
+    // Print table
+    wprintf("ca[] = '%.*s'\n", ca);
+    for (mid = 0; mid < high; mid++)
+    {
+        pca = table[mid];
+        wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
+    }
+*/
+
+    // Do binary search
+    while (low < high)
+    {
+        mid = (low + high) >> 1;
+        pca = table[mid];
+        c = ca.length - pca.length;
+        if (c == 0)
+        {
+            c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof);
+            if (c == 0)
+            {   //printf("found %d\n", mid);
+                return mid;
+            }
+        }
+        if (c < 0)
+        {
+            high = mid;
+        }
+        else
+        {
+            low = mid + 1;
+        }
+    }
+    //printf("not found\n");
+    return -1;              // not found
+}
+
+
+unittest
+{
+    switch (cast(wchar []) "c")
+    {
+         case "coo":
+         default:
+             break;
+    }
+}
+
+
+/**********************************
+ * Same thing, but for wide chars.
+ */
+
+int _d_switch_dstring(dchar[][] table, dchar[] ca)
+in
+{
+    //printf("in _d_switch_dstring()\n");
+    assert(table.length >= 0);
+    assert(ca.length >= 0);
+
+    // Make sure table[] is sorted correctly
+    int j;
+
+    for (j = 1; j < table.length; j++)
+    {
+        int len1 = table[j - 1].length;
+        int len2 = table[j].length;
+
+        assert(len1 <= len2);
+        if (len1 == len2)
+        {
+            int c;
+
+            c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof);
+            assert(c < 0);  // c==0 means a duplicate
+        }
+    }
+}
+out (result)
+{
+    int i;
+    int c;
+
+    //printf("out _d_switch_string()\n");
+    if (result == -1)
+    {
+        // Not found
+        for (i = 0; i < table.length; i++)
+        {
+            if (table[i].length == ca.length)
+            {   c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
+                assert(c != 0);
+            }
+        }
+    }
+    else
+    {
+        assert(0 <= result && result < table.length);
+        for (i = 0; 1; i++)
+        {
+            assert(i < table.length);
+            if (table[i].length == ca.length)
+            {
+                c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
+                if (c == 0)
+                {
+                    assert(i == result);
+                    break;
+                }
+            }
+        }
+    }
+}
+body
+{
+    //printf("body _d_switch_ustring()\n");
+    int low;
+    int high;
+    int mid;
+    int c;
+    dchar[] pca;
+
+    low = 0;
+    high = table.length;
+
+/*
+    // Print table
+    wprintf("ca[] = '%.*s'\n", ca);
+    for (mid = 0; mid < high; mid++)
+    {
+        pca = table[mid];
+        wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
+    }
+*/
+
+    // Do binary search
+    while (low < high)
+    {
+        mid = (low + high) >> 1;
+        pca = table[mid];
+        c = ca.length - pca.length;
+        if (c == 0)
+        {
+            c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof);
+            if (c == 0)
+            {   //printf("found %d\n", mid);
+                return mid;
+            }
+        }
+        if (c < 0)
+        {
+            high = mid;
+        }
+        else
+        {
+            low = mid + 1;
+        }
+    }
+    //printf("not found\n");
+    return -1; // not found
+}
+
+
+unittest
+{
+    switch (cast(dchar []) "c")
+    {
+         case "coo":
+         default:
+             break;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/tls.S	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,44 @@
+/**
+ * Contains support code for thread-local storage.
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#if linux
+
+/* The memory between the addresses of _tlsstart and _tlsend is the storage for
+ * thread-local data in D 2.0.  Both of these rely on the default linker script
+ * of:
+ *      .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ *      .tbss  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ * to group the sections in that order.
+ *
+ * Sadly, this does not work because ld orders .tdata after .tdata.*, despite
+ * what the linker script says.
+ */
+
+.file "tls.S"
+
+.globl _tlsstart
+    .section .tdata,"awT",@progbits
+    .align 4
+    .type   _tlsstart, @object
+    .size   _tlsstart, 4
+_tlsstart:
+    .long   3
+
+.globl _tlsend
+    .section .tcommon,"awT",@nobits
+    .align 4
+    .type   _tlsend, @object
+    .size   _tlsend, 4
+_tlsend:
+    .zero   4
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/trace.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,919 @@
+/**
+ * Contains support code for code profiling.
+ *
+ * Copyright: Copyright Digital Mars 1995 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 1995 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.trace;
+
+private
+{
+    import rt.util.string;
+    import core.stdc.ctype;
+    import core.stdc.stdio;
+    import core.stdc.string;
+    import core.stdc.stdlib;
+}
+
+extern (C):
+
+char* unmangle_ident(char*);    // from DMC++ runtime library
+
+alias long timer_t;
+
+/////////////////////////////////////
+//
+
+struct SymPair
+{
+    SymPair* next;
+    Symbol* sym;        // function that is called
+    uint count;         // number of times sym is called
+}
+
+/////////////////////////////////////
+// A Symbol for each function name.
+
+struct Symbol
+{
+        Symbol* Sl, Sr;         // left, right children
+        SymPair* Sfanin;        // list of calling functions
+        SymPair* Sfanout;       // list of called functions
+        timer_t totaltime;      // aggregate time
+        timer_t functime;       // time excluding subfunction calls
+        ubyte Sflags;
+        char[] Sident;          // name of symbol
+}
+
+const ubyte SFvisited = 1;      // visited
+
+
+//////////////////////////////////
+// Build a linked list of these.
+
+struct Stack
+{
+    Stack* prev;
+    Symbol* sym;
+    timer_t starttime;          // time when function was entered
+    timer_t ohd;                // overhead of all the bookkeeping code
+    timer_t subtime;            // time used by all subfunctions
+}
+
+__gshared			// doesn't work with multithreaded code anyway
+{
+    Symbol* root;            // root of symbol table
+
+    Stack* stack_freelist;
+    Stack* trace_tos;                // top of stack
+    int trace_inited;                // !=0 if initialized
+    timer_t trace_ohd;
+
+    Symbol** psymbols;
+    uint nsymbols;           // number of symbols
+
+    string trace_logfilename = "trace.log";
+    FILE* fplog;
+
+    string trace_deffilename = "trace.def";
+    FILE* fpdef;
+}
+
+////////////////////////////////////////
+// Set file name for output.
+// A file name of "" means write results to stdout.
+// Returns:
+//      0       success
+//      !=0     failure
+
+int trace_setlogfilename(string name)
+{
+    trace_logfilename = name;
+    return 0;
+}
+
+////////////////////////////////////////
+// Set file name for output.
+// A file name of "" means write results to stdout.
+// Returns:
+//      0       success
+//      !=0     failure
+
+int trace_setdeffilename(string name)
+{
+    trace_deffilename = name;
+    return 0;
+}
+
+////////////////////////////////////////
+// Output optimal function link order.
+
+static void trace_order(Symbol *s)
+{
+    while (s)
+    {
+        trace_place(s,0);
+        if (s.Sl)
+            trace_order(s.Sl);
+        s = s.Sr;
+    }
+}
+
+//////////////////////////////////////////////
+//
+
+static Stack* stack_malloc()
+{   Stack *s;
+
+    if (stack_freelist)
+    {   s = stack_freelist;
+        stack_freelist = s.prev;
+    }
+    else
+        s = cast(Stack *)trace_malloc(Stack.sizeof);
+    return s;
+}
+
+//////////////////////////////////////////////
+//
+
+static void stack_free(Stack *s)
+{
+    s.prev = stack_freelist;
+    stack_freelist = s;
+}
+
+//////////////////////////////////////
+// Qsort() comparison routine for array of pointers to SymPair's.
+
+static int sympair_cmp(in void* e1, in void* e2)
+{   SymPair** psp1;
+    SymPair** psp2;
+
+    psp1 = cast(SymPair**)e1;
+    psp2 = cast(SymPair**)e2;
+
+    return (*psp2).count - (*psp1).count;
+}
+
+//////////////////////////////////////
+// Place symbol s, and then place any fan ins or fan outs with
+// counts greater than count.
+
+static void trace_place(Symbol *s, uint count)
+{   SymPair* sp;
+    SymPair** base;
+
+    if (!(s.Sflags & SFvisited))
+    {   size_t num;
+        uint u;
+
+        //printf("\t%.*s\t%u\n", s.Sident, count);
+        fprintf(fpdef,"\t%.*s\n", s.Sident);
+        s.Sflags |= SFvisited;
+
+        // Compute number of items in array
+        num = 0;
+        for (sp = s.Sfanin; sp; sp = sp.next)
+            num++;
+        for (sp = s.Sfanout; sp; sp = sp.next)
+            num++;
+        if (!num)
+            return;
+
+        // Allocate and fill array
+        base = cast(SymPair**)trace_malloc(SymPair.sizeof * num);
+        u = 0;
+        for (sp = s.Sfanin; sp; sp = sp.next)
+            base[u++] = sp;
+        for (sp = s.Sfanout; sp; sp = sp.next)
+            base[u++] = sp;
+
+        // Sort array
+        qsort(base, num, (SymPair *).sizeof, &sympair_cmp);
+
+        //for (u = 0; u < num; u++)
+            //printf("\t\t%.*s\t%u\n", base[u].sym.Sident, base[u].count);
+
+        // Place symbols
+        for (u = 0; u < num; u++)
+        {
+            if (base[u].count >= count)
+            {   uint u2;
+                uint c2;
+
+                u2 = (u + 1 < num) ? u + 1 : u;
+                c2 = base[u2].count;
+                if (c2 < count)
+                    c2 = count;
+                trace_place(base[u].sym,c2);
+            }
+            else
+                break;
+        }
+
+        // Clean up
+        trace_free(base);
+    }
+}
+
+/////////////////////////////////////
+// Initialize and terminate.
+
+static this()
+{
+    trace_init();
+}
+
+static ~this()
+{
+    trace_term();
+}
+
+///////////////////////////////////
+// Report results.
+// Also compute nsymbols.
+
+static void trace_report(Symbol* s)
+{   SymPair* sp;
+    uint count;
+
+    //printf("trace_report()\n");
+    while (s)
+    {   nsymbols++;
+        if (s.Sl)
+            trace_report(s.Sl);
+        fprintf(fplog,"------------------\n");
+        count = 0;
+        for (sp = s.Sfanin; sp; sp = sp.next)
+        {
+            fprintf(fplog,"\t%5d\t%.*s\n", sp.count, sp.sym.Sident);
+            count += sp.count;
+        }
+        fprintf(fplog,"%.*s\t%u\t%lld\t%lld\n",s.Sident,count,s.totaltime,s.functime);
+        for (sp = s.Sfanout; sp; sp = sp.next)
+        {
+            fprintf(fplog,"\t%5d\t%.*s\n",sp.count,sp.sym.Sident);
+        }
+        s = s.Sr;
+    }
+}
+
+////////////////////////////////////
+// Allocate and fill array of symbols.
+
+static void trace_array(Symbol *s)
+{
+    __gshared uint u;
+
+    if (!psymbols)
+    {   u = 0;
+        psymbols = cast(Symbol **)trace_malloc((Symbol *).sizeof * nsymbols);
+    }
+    while (s)
+    {
+        psymbols[u++] = s;
+        trace_array(s.Sl);
+        s = s.Sr;
+    }
+}
+
+
+//////////////////////////////////////
+// Qsort() comparison routine for array of pointers to Symbol's.
+
+static int symbol_cmp(in void* e1, in void* e2)
+{   Symbol** ps1;
+    Symbol** ps2;
+    timer_t diff;
+
+    ps1 = cast(Symbol **)e1;
+    ps2 = cast(Symbol **)e2;
+
+    diff = (*ps2).functime - (*ps1).functime;
+    return (diff == 0) ? 0 : ((diff > 0) ? 1 : -1);
+}
+
+
+///////////////////////////////////
+// Report function timings
+
+static void trace_times(Symbol* root)
+{   uint u;
+    timer_t freq;
+
+    // Sort array
+    qsort(psymbols, nsymbols, (Symbol *).sizeof, &symbol_cmp);
+
+    // Print array
+    QueryPerformanceFrequency(&freq);
+    fprintf(fplog,"\n======== Timer Is %lld Ticks/Sec, Times are in Microsecs ========\n\n",freq);
+    fprintf(fplog,"  Num          Tree        Func        Per\n");
+    fprintf(fplog,"  Calls        Time        Time        Call\n\n");
+    for (u = 0; u < nsymbols; u++)
+    {   Symbol* s = psymbols[u];
+        timer_t tl,tr;
+        timer_t fl,fr;
+        timer_t pl,pr;
+        timer_t percall;
+        SymPair* sp;
+        uint calls;
+        char[] id;
+
+        version (Windows)
+        {
+            char* p = (s.Sident ~ '\0').ptr;
+            p = unmangle_ident(p);
+            if (p)
+                id = p[0 .. strlen(p)];
+        }
+        if (!id)
+            id = s.Sident;
+        calls = 0;
+        for (sp = s.Sfanin; sp; sp = sp.next)
+            calls += sp.count;
+        if (calls == 0)
+            calls = 1;
+
+version (all)
+{
+        tl = (s.totaltime * 1000000) / freq;
+        fl = (s.functime  * 1000000) / freq;
+        percall = s.functime / calls;
+        pl = (s.functime * 1000000) / calls / freq;
+
+        fprintf(fplog,"%7d%12lld%12lld%12lld     %.*s\n",
+            calls,tl,fl,pl,id);
+}
+else
+{
+        tl = s.totaltime / freq;
+        tr = ((s.totaltime - tl * freq) * 10000000) / freq;
+
+        fl = s.functime  / freq;
+        fr = ((s.functime  - fl * freq) * 10000000) / freq;
+
+        percall = s.functime / calls;
+        pl = percall  / freq;
+        pr = ((percall  - pl * freq) * 10000000) / freq;
+
+        fprintf(fplog,"%7d\t%3lld.%07lld\t%3lld.%07lld\t%3lld.%07lld\t%.*s\n",
+            calls,tl,tr,fl,fr,pl,pr,id);
+}
+        if (id !is s.Sident)
+            free(id.ptr);
+    }
+}
+
+
+///////////////////////////////////
+// Initialize.
+
+static void trace_init()
+{
+    if (!trace_inited)
+    {
+        trace_inited = 1;
+
+        {   // See if we can determine the overhead.
+            uint u;
+            timer_t starttime;
+            timer_t endtime;
+            Stack *st;
+
+            st = trace_tos;
+            trace_tos = null;
+            QueryPerformanceCounter(&starttime);
+            for (u = 0; u < 100; u++)
+            {
+                asm
+                {
+                    call _trace_pro_n   ;
+                    db   0              ;
+                    call _trace_epi_n   ;
+                }
+            }
+            QueryPerformanceCounter(&endtime);
+            trace_ohd = (endtime - starttime) / u;
+            //printf("trace_ohd = %lld\n",trace_ohd);
+            if (trace_ohd > 0)
+                trace_ohd--;            // round down
+            trace_tos = st;
+        }
+    }
+}
+
+/////////////////////////////////
+// Terminate.
+
+void trace_term()
+{
+    //printf("trace_term()\n");
+    if (trace_inited == 1)
+    {   Stack *n;
+
+        trace_inited = 2;
+
+        // Free remainder of the stack
+        while (trace_tos)
+        {
+            n = trace_tos.prev;
+            stack_free(trace_tos);
+            trace_tos = n;
+        }
+
+        while (stack_freelist)
+        {
+            n = stack_freelist.prev;
+            stack_free(stack_freelist);
+            stack_freelist = n;
+        }
+
+        // Merge in data from any existing file
+        trace_merge();
+
+        // Report results
+        fplog = fopen(trace_logfilename.ptr, "w");
+        if (fplog)
+        {   nsymbols = 0;
+            trace_report(root);
+            trace_array(root);
+            trace_times(root);
+            fclose(fplog);
+        }
+
+        // Output function link order
+        fpdef = fopen(trace_deffilename.ptr,"w");
+        if (fpdef)
+        {   fprintf(fpdef,"\nFUNCTIONS\n");
+            trace_order(root);
+            fclose(fpdef);
+        }
+
+        trace_free(psymbols);
+        psymbols = null;
+    }
+}
+
+/////////////////////////////////
+// Our storage allocator.
+
+static void *trace_malloc(size_t nbytes)
+{   void *p;
+
+    p = malloc(nbytes);
+    if (!p)
+        exit(EXIT_FAILURE);
+    return p;
+}
+
+static void trace_free(void *p)
+{
+    free(p);
+}
+
+//////////////////////////////////////////////
+//
+
+static Symbol* trace_addsym(char[] id)
+{
+    Symbol** parent;
+    Symbol* rover;
+    Symbol* s;
+    int cmp;
+    char c;
+
+    //printf("trace_addsym('%s',%d)\n",p,len);
+    parent = &root;
+    rover = *parent;
+    while (rover !is null)               // while we haven't run out of tree
+    {
+        cmp = dstrcmp(id, rover.Sident);
+        if (cmp == 0)
+        {
+            return rover;
+        }
+        parent = (cmp < 0) ?            /* if we go down left side      */
+            &(rover.Sl) :               /* then get left child          */
+            &(rover.Sr);                /* else get right child         */
+        rover = *parent;                /* get child                    */
+    }
+    /* not in table, so insert into table       */
+    s = cast(Symbol *)trace_malloc(Symbol.sizeof);
+    memset(s,0,Symbol.sizeof);
+    s.Sident = id;
+    *parent = s;                        // link new symbol into tree
+    return s;
+}
+
+/***********************************
+ * Add symbol s with count to SymPair list.
+ */
+
+static void trace_sympair_add(SymPair** psp, Symbol* s, uint count)
+{   SymPair* sp;
+
+    for (; 1; psp = &sp.next)
+    {
+        sp = *psp;
+        if (!sp)
+        {
+            sp = cast(SymPair *)trace_malloc(SymPair.sizeof);
+            sp.sym = s;
+            sp.count = 0;
+            sp.next = null;
+            *psp = sp;
+            break;
+        }
+        else if (sp.sym == s)
+        {
+            break;
+        }
+    }
+    sp.count += count;
+}
+
+//////////////////////////////////////////////
+//
+
+static void trace_pro(char[] id)
+{
+    Stack* n;
+    Symbol* s;
+    timer_t starttime;
+    timer_t t;
+
+    QueryPerformanceCounter(&starttime);
+    if (id.length == 0)
+        return;
+    if (!trace_inited)
+        trace_init();                   // initialize package
+    n = stack_malloc();
+    n.prev = trace_tos;
+    trace_tos = n;
+    s = trace_addsym(id);
+    trace_tos.sym = s;
+    if (trace_tos.prev)
+    {
+        Symbol* prev;
+        int i;
+
+        // Accumulate Sfanout and Sfanin
+        prev = trace_tos.prev.sym;
+        trace_sympair_add(&prev.Sfanout,s,1);
+        trace_sympair_add(&s.Sfanin,prev,1);
+    }
+    QueryPerformanceCounter(&t);
+    trace_tos.starttime = starttime;
+    trace_tos.ohd = trace_ohd + t - starttime;
+    trace_tos.subtime = 0;
+    //printf("trace_tos.ohd=%lld, trace_ohd=%lld + t=%lld - starttime=%lld\n",
+    //  trace_tos.ohd,trace_ohd,t,starttime);
+}
+
+/////////////////////////////////////////
+//
+
+static void trace_epi()
+{   Stack* n;
+    timer_t endtime;
+    timer_t t;
+    timer_t ohd;
+
+    //printf("trace_epi()\n");
+    if (trace_tos)
+    {
+        timer_t starttime;
+        timer_t totaltime;
+
+        QueryPerformanceCounter(&endtime);
+        starttime = trace_tos.starttime;
+        totaltime = endtime - starttime - trace_tos.ohd;
+        if (totaltime < 0)
+        {   //printf("endtime=%lld - starttime=%lld - trace_tos.ohd=%lld < 0\n",
+            //  endtime,starttime,trace_tos.ohd);
+            totaltime = 0;              // round off error, just make it 0
+        }
+
+        // totaltime is time spent in this function + all time spent in
+        // subfunctions - bookkeeping overhead.
+        trace_tos.sym.totaltime += totaltime;
+
+        //if (totaltime < trace_tos.subtime)
+        //printf("totaltime=%lld < trace_tos.subtime=%lld\n",totaltime,trace_tos.subtime);
+        trace_tos.sym.functime  += totaltime - trace_tos.subtime;
+        ohd = trace_tos.ohd;
+        n = trace_tos.prev;
+        stack_free(trace_tos);
+        trace_tos = n;
+        if (n)
+        {   QueryPerformanceCounter(&t);
+            n.ohd += ohd + t - endtime;
+            n.subtime += totaltime;
+            //printf("n.ohd = %lld\n",n.ohd);
+        }
+    }
+}
+
+
+////////////////////////// FILE INTERFACE /////////////////////////
+
+/////////////////////////////////////
+// Read line from file fp.
+// Returns:
+//      trace_malloc'd line buffer
+//      null if end of file
+
+static char* trace_readline(FILE* fp)
+{   int c;
+    int dim;
+    int i;
+    char *buf;
+
+    //printf("trace_readline(%p)\n", fp);
+    i = 0;
+    dim = 0;
+    buf = null;
+    while (1)
+    {
+        if (i == dim)
+        {   char *p;
+
+            dim += 80;
+            p = cast(char *)trace_malloc(dim);
+            memcpy(p,buf,i);
+            trace_free(buf);
+            buf = p;
+        }
+        c = fgetc(fp);
+        switch (c)
+        {
+            case EOF:
+                if (i == 0)
+                {   trace_free(buf);
+                    return null;
+                }
+            case '\n':
+                goto L1;
+            default:
+                break;
+        }
+        buf[i] = cast(char)c;
+        i++;
+    }
+L1:
+    buf[i] = 0;
+    //printf("line '%s'\n",buf);
+    return buf;
+}
+
+//////////////////////////////////////
+// Skip space
+
+static char *skipspace(char *p)
+{
+    while (isspace(*p))
+        p++;
+    return p;
+}
+
+////////////////////////////////////////////////////////
+// Merge in profiling data from existing file.
+
+static void trace_merge()
+{   FILE *fp;
+    char *buf;
+    char *p;
+    uint count;
+    Symbol *s;
+    SymPair *sfanin;
+    SymPair **psp;
+
+    if (trace_logfilename && (fp = fopen(trace_logfilename.ptr,"r")) !is null)
+    {
+        buf = null;
+        sfanin = null;
+        psp = &sfanin;
+        while (1)
+        {
+            trace_free(buf);
+            buf = trace_readline(fp);
+            if (!buf)
+                break;
+            switch (*buf)
+            {
+                case '=':               // ignore rest of file
+                    trace_free(buf);
+                    goto L1;
+                case ' ':
+                case '\t':              // fan in or fan out line
+                    count = strtoul(buf,&p,10);
+                    if (p == buf)       // if invalid conversion
+                        continue;
+                    p = skipspace(p);
+                    if (!*p)
+                        continue;
+                    s = trace_addsym(p[0 .. strlen(p)]);
+                    trace_sympair_add(psp,s,count);
+                    break;
+                default:
+                    if (!isalpha(*buf))
+                    {
+                        if (!sfanin)
+                            psp = &sfanin;
+                        continue;       // regard unrecognized line as separator
+                    }
+                case '?':
+                case '_':
+                case '$':
+                case '@':
+                    p = buf;
+                    while (isgraph(*p))
+                        p++;
+                    *p = 0;
+                    //printf("trace_addsym('%s')\n",buf);
+                    s = trace_addsym(buf[0 .. strlen(buf)]);
+                    if (s.Sfanin)
+                    {   SymPair *sp;
+
+                        for (; sfanin; sfanin = sp)
+                        {
+                            trace_sympair_add(&s.Sfanin,sfanin.sym,sfanin.count);
+                            sp = sfanin.next;
+                            trace_free(sfanin);
+                        }
+                    }
+                    else
+                    {   s.Sfanin = sfanin;
+                    }
+                    sfanin = null;
+                    psp = &s.Sfanout;
+
+                    {   timer_t t;
+
+                        p++;
+                        count = strtoul(p,&p,10);
+                        t = cast(long)strtoull(p,&p,10);
+                        s.totaltime += t;
+                        t = cast(long)strtoull(p,&p,10);
+                        s.functime += t;
+                    }
+                    break;
+            }
+        }
+    L1:
+        fclose(fp);
+    }
+}
+
+////////////////////////// COMPILER INTERFACE /////////////////////
+
+/////////////////////////////////////////////
+// Function called by trace code in function prolog.
+
+void _trace_pro_n()
+{
+    /* Length of string is either:
+     *  db      length
+     *  ascii   string
+     * or:
+     *  db      0x0FF
+     *  db      0
+     *  dw      length
+     *  ascii   string
+     */
+
+  version (OSX)
+  { // 16 byte align stack
+    asm
+    {   naked                           ;
+        pushad                          ;
+        mov     ECX,8*4[ESP]            ;
+        xor     EAX,EAX                 ;
+        mov     AL,[ECX]                ;
+        cmp     AL,0xFF                 ;
+        jne     L1                      ;
+        cmp     byte ptr 1[ECX],0       ;
+        jne     L1                      ;
+        mov     AX,2[ECX]               ;
+        add     8*4[ESP],3              ;
+        add     ECX,3                   ;
+    L1: inc     EAX                     ;
+        inc     ECX                     ;
+        add     8*4[ESP],EAX            ;
+        dec     EAX                     ;
+        sub     ESP,4                   ;
+        push    ECX                     ;
+        push    EAX                     ;
+        call    trace_pro               ;
+        add     ESP,12                  ;
+        popad                           ;
+        ret                             ;
+    }
+  }
+  else
+  {
+    asm
+    {   naked                           ;
+        pushad                          ;
+        mov     ECX,8*4[ESP]            ;
+        xor     EAX,EAX                 ;
+        mov     AL,[ECX]                ;
+        cmp     AL,0xFF                 ;
+        jne     L1                      ;
+        cmp     byte ptr 1[ECX],0       ;
+        jne     L1                      ;
+        mov     AX,2[ECX]               ;
+        add     8*4[ESP],3              ;
+        add     ECX,3                   ;
+    L1: inc     EAX                     ;
+        inc     ECX                     ;
+        add     8*4[ESP],EAX            ;
+        dec     EAX                     ;
+        push    ECX                     ;
+        push    EAX                     ;
+        call    trace_pro               ;
+        add     ESP,8                   ;
+        popad                           ;
+        ret                             ;
+    }
+  }
+}
+
+/////////////////////////////////////////////
+// Function called by trace code in function epilog.
+
+
+void _trace_epi_n()
+{
+  version (OSX)
+  { // 16 byte align stack
+    asm
+    {   naked   ;
+        pushad  ;
+        sub     ESP,12  ;
+    }
+    trace_epi();
+    asm
+    {
+        add     ESP,12  ;
+        popad   ;
+        ret     ;
+    }
+  }
+  else
+  {
+    asm
+    {   naked   ;
+        pushad  ;
+    }
+    trace_epi();
+    asm
+    {
+        popad   ;
+        ret     ;
+    }
+  }
+}
+
+
+version (Windows)
+{
+    extern (Windows)
+    {
+        export int QueryPerformanceCounter(timer_t *);
+        export int QueryPerformanceFrequency(timer_t *);
+    }
+}
+else version (X86)
+{
+    extern (D)
+    {
+        void QueryPerformanceCounter(timer_t* ctr)
+        {
+            asm
+            {   naked                   ;
+                mov       ECX,EAX       ;
+                rdtsc                   ;
+                mov   [ECX],EAX         ;
+                mov   4[ECX],EDX        ;
+                ret                     ;
+            }
+        }
+
+        void QueryPerformanceFrequency(timer_t* freq)
+        {
+            *freq = 3579545;
+        }
+    }
+}
+else
+{
+    static assert(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_AC.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,107 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_AC;
+
+// Object[]
+
+class TypeInfo_AC : TypeInfo
+{
+    override hash_t getHash(in void* p)
+    {   Object[] s = *cast(Object[]*)p;
+        hash_t hash = 0;
+
+        foreach (Object o; s)
+        {
+            if (o)
+                hash += o.toHash();
+        }
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        Object[] s1 = *cast(Object[]*)p1;
+        Object[] s2 = *cast(Object[]*)p2;
+
+        if (s1.length == s2.length)
+        {
+            for (size_t u = 0; u < s1.length; u++)
+            {   Object o1 = s1[u];
+                Object o2 = s2[u];
+
+                // Do not pass null's to Object.opEquals()
+                if (o1 is o2 ||
+                    (!(o1 is null) && !(o2 is null) && o1.opEquals(o2)))
+                    continue;
+                return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        Object[] s1 = *cast(Object[]*)p1;
+        Object[] s2 = *cast(Object[]*)p2;
+        ptrdiff_t c;
+
+        c = cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length;
+        if (c == 0)
+        {
+            for (size_t u = 0; u < s1.length; u++)
+            {   Object o1 = s1[u];
+                Object o2 = s2[u];
+
+                if (o1 is o2)
+                    continue;
+
+                // Regard null references as always being "less than"
+                if (o1)
+                {
+                    if (!o2)
+                    {   c = 1;
+                        break;
+                    }
+                    c = o1.opCmp(o2);
+                    if (c)
+                        break;
+                }
+                else
+                {   c = -1;
+                    break;
+                }
+            }
+        }
+        if (c < 0)
+            c = -1;
+        else if (c > 0)
+            c = 1;
+        return c;
+    }
+
+    override size_t tsize()
+    {
+        return (Object[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(Object);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_Acdouble.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,94 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Acdouble;
+
+private import rt.typeinfo.ti_cdouble;
+
+// cdouble[]
+
+class TypeInfo_Ar : TypeInfo
+{
+    override string toString() { return "cdouble[]"; }
+
+    override hash_t getHash(in void* p)
+    {   cdouble[] s = *cast(cdouble[]*)p;
+        size_t len = s.length;
+        cdouble *str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += (cast(uint *)str)[0];
+            hash += (cast(uint *)str)[1];
+            hash += (cast(uint *)str)[2];
+            hash += (cast(uint *)str)[3];
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        cdouble[] s1 = *cast(cdouble[]*)p1;
+        cdouble[] s2 = *cast(cdouble[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return false;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_r._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        cdouble[] s1 = *cast(cdouble[]*)p1;
+        cdouble[] s2 = *cast(cdouble[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_r._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (cdouble[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(cdouble);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_Acfloat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,92 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Acfloat;
+
+private import rt.typeinfo.ti_cfloat;
+
+// cfloat[]
+
+class TypeInfo_Aq : TypeInfo
+{
+    override string toString() { return "cfloat[]"; }
+
+    override hash_t getHash(in void* p)
+    {   cfloat[] s = *cast(cfloat[]*)p;
+        size_t len = s.length;
+        cfloat *str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += (cast(uint *)str)[0];
+            hash += (cast(uint *)str)[1];
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        cfloat[] s1 = *cast(cfloat[]*)p1;
+        cfloat[] s2 = *cast(cfloat[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return false;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_q._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        cfloat[] s1 = *cast(cfloat[]*)p1;
+        cfloat[] s2 = *cast(cfloat[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_q._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (cfloat[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(cfloat);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_Acreal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,95 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Acreal;
+
+private import rt.typeinfo.ti_creal;
+
+// creal[]
+
+class TypeInfo_Ac : TypeInfo
+{
+    override string toString() { return "creal[]"; }
+
+    override hash_t getHash(in void* p)
+    {   creal[] s = *cast(creal[]*)p;
+        size_t len = s.length;
+        creal *str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += (cast(uint *)str)[0];
+            hash += (cast(uint *)str)[1];
+            hash += (cast(uint *)str)[2];
+            hash += (cast(uint *)str)[3];
+            hash += (cast(uint *)str)[4];
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        creal[] s1 = *cast(creal[]*)p1;
+        creal[] s2 = *cast(creal[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return 0;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_c._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        creal[] s1 = *cast(creal[]*)p1;
+        creal[] s2 = *cast(creal[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_c._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (creal[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(creal);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_Adouble.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,104 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Adouble;
+
+private import rt.typeinfo.ti_double;
+
+// double[]
+
+class TypeInfo_Ad : TypeInfo
+{
+    override string toString() { return "double[]"; }
+
+    override hash_t getHash(in void* p)
+    {   double[] s = *cast(double[]*)p;
+        size_t len = s.length;
+        auto str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += (cast(uint *)str)[0];
+            hash += (cast(uint *)str)[1];
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        double[] s1 = *cast(double[]*)p1;
+        double[] s2 = *cast(double[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return 0;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_d._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        double[] s1 = *cast(double[]*)p1;
+        double[] s2 = *cast(double[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_d._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (double[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(double);
+    }
+}
+
+// idouble[]
+
+class TypeInfo_Ap : TypeInfo_Ad
+{
+    override string toString() { return "idouble[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(idouble);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_Afloat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,103 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Afloat;
+
+private import rt.typeinfo.ti_float;
+
+// float[]
+
+class TypeInfo_Af : TypeInfo
+{
+    override string toString() { return "float[]"; }
+
+    override hash_t getHash(in void* p)
+    {   float[] s = *cast(float[]*)p;
+        size_t len = s.length;
+        auto str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += *cast(uint *)str;
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        float[] s1 = *cast(float[]*)p1;
+        float[] s2 = *cast(float[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return 0;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_f._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        float[] s1 = *cast(float[]*)p1;
+        float[] s2 = *cast(float[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_f._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (float[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(float);
+    }
+}
+
+// ifloat[]
+
+class TypeInfo_Ao : TypeInfo_Af
+{
+    override string toString() { return "ifloat[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(ifloat);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_Ag.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,228 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Ag;
+
+private import rt.util.string;
+private import core.stdc.string;
+
+// byte[]
+
+class TypeInfo_Ag : TypeInfo
+{
+    override string toString() { return "byte[]"; }
+
+    override hash_t getHash(in void* p)
+    {   byte[] s = *cast(byte[]*)p;
+        size_t len = s.length;
+        byte *str = s.ptr;
+        hash_t hash = 0;
+
+        while (1)
+        {
+            switch (len)
+            {
+                case 0:
+                    return hash;
+
+                case 1:
+                    hash *= 9;
+                    hash += *cast(ubyte *)str;
+                    return hash;
+
+                case 2:
+                    hash *= 9;
+                    hash += *cast(ushort *)str;
+                    return hash;
+
+                case 3:
+                    hash *= 9;
+                    hash += (*cast(ushort *)str << 8) +
+                            (cast(ubyte *)str)[2];
+                    return hash;
+
+                default:
+                    hash *= 9;
+                    hash += *cast(uint *)str;
+                    str += 4;
+                    len -= 4;
+                    break;
+            }
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        byte[] s1 = *cast(byte[]*)p1;
+        byte[] s2 = *cast(byte[]*)p2;
+
+        return s1.length == s2.length &&
+               memcmp(cast(byte *)s1, cast(byte *)s2, s1.length) == 0;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        byte[] s1 = *cast(byte[]*)p1;
+        byte[] s2 = *cast(byte[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = s1[u] - s2[u];
+            if (result)
+                return result;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (byte[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(byte);
+    }
+}
+
+
+// ubyte[]
+
+class TypeInfo_Ah : TypeInfo_Ag
+{
+    override string toString() { return "ubyte[]"; }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        char[] s1 = *cast(char[]*)p1;
+        char[] s2 = *cast(char[]*)p2;
+
+        return dstrcmp(s1, s2);
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(ubyte);
+    }
+}
+
+// void[]
+
+class TypeInfo_Av : TypeInfo_Ah
+{
+    override string toString() { return "void[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(void);
+    }
+}
+
+// bool[]
+
+class TypeInfo_Ab : TypeInfo_Ah
+{
+    override string toString() { return "bool[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(bool);
+    }
+}
+
+// char[]
+
+class TypeInfo_Aa : TypeInfo_Ag
+{
+    override string toString() { return "char[]"; }
+
+    override hash_t getHash(in void* p)
+    {   char[] s = *cast(char[]*)p;
+        hash_t hash = 0;
+
+version (all)
+{
+        foreach (char c; s)
+            hash = hash * 11 + c;
+}
+else
+{
+        size_t len = s.length;
+        char *str = s;
+
+        while (1)
+        {
+            switch (len)
+            {
+                case 0:
+                    return hash;
+
+                case 1:
+                    hash *= 9;
+                    hash += *cast(ubyte *)str;
+                    return hash;
+
+                case 2:
+                    hash *= 9;
+                    hash += *cast(ushort *)str;
+                    return hash;
+
+                case 3:
+                    hash *= 9;
+                    hash += (*cast(ushort *)str << 8) +
+                            (cast(ubyte *)str)[2];
+                    return hash;
+
+                default:
+                    hash *= 9;
+                    hash += *cast(uint *)str;
+                    str += 4;
+                    len -= 4;
+                    break;
+            }
+        }
+}
+        return hash;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(char);
+    }
+}
+
+// string
+
+class TypeInfo_Aya : TypeInfo_Aa
+{
+    override string toString() { return "immutable(char)[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(immutable(char));
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_Aint.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,140 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Aint;
+
+private import core.stdc.string;
+
+// int[]
+
+class TypeInfo_Ai : TypeInfo
+{
+    override string toString() { return "int[]"; }
+
+    override hash_t getHash(in void* p)
+    {   int[] s = *cast(int[]*)p;
+        auto len = s.length;
+        auto str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += *cast(uint *)str;
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        int[] s1 = *cast(int[]*)p1;
+        int[] s2 = *cast(int[]*)p2;
+
+        return s1.length == s2.length &&
+               memcmp(cast(void *)s1, cast(void *)s2, s1.length * int.sizeof) == 0;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        int[] s1 = *cast(int[]*)p1;
+        int[] s2 = *cast(int[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = s1[u] - s2[u];
+            if (result)
+                return result;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (int[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(int);
+    }
+}
+
+unittest
+{
+    int[][] a = [[5,3,8,7], [2,5,3,8,7]];
+    a.sort;
+    assert(a == [[2,5,3,8,7], [5,3,8,7]]);
+
+    a = [[5,3,8,7], [5,3,8]];
+    a.sort;
+    assert(a == [[5,3,8], [5,3,8,7]]);
+}
+
+// uint[]
+
+class TypeInfo_Ak : TypeInfo_Ai
+{
+    override string toString() { return "uint[]"; }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        uint[] s1 = *cast(uint[]*)p1;
+        uint[] s2 = *cast(uint[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = s1[u] - s2[u];
+            if (result)
+                return result;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(uint);
+    }
+}
+
+// dchar[]
+
+class TypeInfo_Aw : TypeInfo_Ak
+{
+    override string toString() { return "dchar[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(dchar);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_Along.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,120 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Along;
+
+private import core.stdc.string;
+
+// long[]
+
+class TypeInfo_Al : TypeInfo
+{
+    override string toString() { return "long[]"; }
+
+    override hash_t getHash(in void* p)
+    {   long[] s = *cast(long[]*)p;
+        size_t len = s.length;
+        auto str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += *cast(uint *)str + *(cast(uint *)str + 1);
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        long[] s1 = *cast(long[]*)p1;
+        long[] s2 = *cast(long[]*)p2;
+
+        return s1.length == s2.length &&
+               memcmp(cast(void *)s1, cast(void *)s2, s1.length * long.sizeof) == 0;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        long[] s1 = *cast(long[]*)p1;
+        long[] s2 = *cast(long[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (s1[u] < s2[u])
+                return -1;
+            else if (s1[u] > s2[u])
+                return 1;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (long[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(long);
+    }
+}
+
+
+// ulong[]
+
+class TypeInfo_Am : TypeInfo_Al
+{
+    override string toString() { return "ulong[]"; }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        ulong[] s1 = *cast(ulong[]*)p1;
+        ulong[] s2 = *cast(ulong[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (s1[u] < s2[u])
+                return -1;
+            else if (s1[u] > s2[u])
+                return 1;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(ulong);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_Areal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,105 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Areal;
+
+private import rt.typeinfo.ti_real;
+
+// real[]
+
+class TypeInfo_Ae : TypeInfo
+{
+    override string toString() { return "real[]"; }
+
+    override hash_t getHash(in void* p)
+    {   real[] s = *cast(real[]*)p;
+        size_t len = s.length;
+        auto str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += (cast(uint *)str)[0];
+            hash += (cast(uint *)str)[1];
+            hash += (cast(ushort *)str)[4];
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        real[] s1 = *cast(real[]*)p1;
+        real[] s2 = *cast(real[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return false;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_e._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        real[] s1 = *cast(real[]*)p1;
+        real[] s2 = *cast(real[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_e._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (real[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(real);
+    }
+}
+
+// ireal[]
+
+class TypeInfo_Aj : TypeInfo_Ae
+{
+    override string toString() { return "ireal[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(ireal);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_Ashort.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,143 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Ashort;
+
+private import core.stdc.string;
+
+// short[]
+
+class TypeInfo_As : TypeInfo
+{
+    override string toString() { return "short[]"; }
+
+    override hash_t getHash(in void* p)
+    {   short[] s = *cast(short[]*)p;
+        size_t len = s.length;
+        short *str = s.ptr;
+        hash_t hash = 0;
+
+        while (1)
+        {
+            switch (len)
+            {
+                case 0:
+                    return hash;
+
+                case 1:
+                    hash *= 9;
+                    hash += *cast(ushort *)str;
+                    return hash;
+
+                default:
+                    hash *= 9;
+                    hash += *cast(uint *)str;
+                    str += 2;
+                    len -= 2;
+                    break;
+            }
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        short[] s1 = *cast(short[]*)p1;
+        short[] s2 = *cast(short[]*)p2;
+
+        return s1.length == s2.length &&
+               memcmp(cast(void *)s1, cast(void *)s2, s1.length * short.sizeof) == 0;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        short[] s1 = *cast(short[]*)p1;
+        short[] s2 = *cast(short[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = s1[u] - s2[u];
+            if (result)
+                return result;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (short[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(short);
+    }
+}
+
+
+// ushort[]
+
+class TypeInfo_At : TypeInfo_As
+{
+    override string toString() { return "ushort[]"; }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        ushort[] s1 = *cast(ushort[]*)p1;
+        ushort[] s2 = *cast(ushort[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = s1[u] - s2[u];
+            if (result)
+                return result;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(ushort);
+    }
+}
+
+// wchar[]
+
+class TypeInfo_Au : TypeInfo_At
+{
+    override string toString() { return "wchar[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(wchar);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_C.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,63 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_C;
+
+// Object
+
+class TypeInfo_C : TypeInfo
+{
+    override hash_t getHash(in void* p)
+    {
+        Object o = *cast(Object*)p;
+        return o ? o.toHash() : 0;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        Object o1 = *cast(Object*)p1;
+        Object o2 = *cast(Object*)p2;
+
+        return o1 == o2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        Object o1 = *cast(Object*)p1;
+        Object o2 = *cast(Object*)p2;
+        int c = 0;
+
+        // Regard null references as always being "less than"
+        if (!(o1 is o2))
+        {
+            if (o1)
+            {   if (!o2)
+                    c = 1;
+                else
+                    c = o1.opCmp(o2);
+            }
+            else
+                c = -1;
+        }
+        return c;
+    }
+
+    override size_t tsize()
+    {
+        return Object.sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_byte.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,49 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_byte;
+
+// byte
+
+class TypeInfo_g : TypeInfo
+{
+    override string toString() { return "byte"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(byte *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(byte *)p1 == *cast(byte *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(byte *)p1 - *cast(byte *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return byte.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        byte t;
+
+        t = *cast(byte *)p1;
+        *cast(byte *)p1 = *cast(byte *)p2;
+        *cast(byte *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_cdouble.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,77 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_cdouble;
+
+// cdouble
+
+class TypeInfo_r : TypeInfo
+{
+    override string toString() { return "cdouble"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
+               (cast(uint *)p)[2] + (cast(uint *)p)[3];
+    }
+
+    static equals_t _equals(cdouble f1, cdouble f2)
+    {
+        return f1 == f2;
+    }
+
+    static int _compare(cdouble f1, cdouble f2)
+    {   int result;
+
+        if (f1.re < f2.re)
+            result = -1;
+        else if (f1.re > f2.re)
+            result = 1;
+        else if (f1.im < f2.im)
+            result = -1;
+        else if (f1.im > f2.im)
+            result = 1;
+        else
+            result = 0;
+        return result;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(cdouble *)p1, *cast(cdouble *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(cdouble *)p1, *cast(cdouble *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return cdouble.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        cdouble t;
+
+        t = *cast(cdouble *)p1;
+        *cast(cdouble *)p1 = *cast(cdouble *)p2;
+        *cast(cdouble *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable cdouble r;
+
+        return (cast(cdouble *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_cfloat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,76 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_cfloat;
+
+// cfloat
+
+class TypeInfo_q : TypeInfo
+{
+    override string toString() { return "cfloat"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return (cast(uint *)p)[0] + (cast(uint *)p)[1];
+    }
+
+    static equals_t _equals(cfloat f1, cfloat f2)
+    {
+        return f1 == f2;
+    }
+
+    static int _compare(cfloat f1, cfloat f2)
+    {   int result;
+
+        if (f1.re < f2.re)
+            result = -1;
+        else if (f1.re > f2.re)
+            result = 1;
+        else if (f1.im < f2.im)
+            result = -1;
+        else if (f1.im > f2.im)
+            result = 1;
+        else
+            result = 0;
+        return result;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(cfloat *)p1, *cast(cfloat *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(cfloat *)p1, *cast(cfloat *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return cfloat.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        cfloat t;
+
+        t = *cast(cfloat *)p1;
+        *cast(cfloat *)p1 = *cast(cfloat *)p2;
+        *cast(cfloat *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable cfloat r;
+
+        return (cast(cfloat *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_char.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,55 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_char;
+
+// char
+
+class TypeInfo_a : TypeInfo
+{
+    override string toString() { return "char"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(char *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(char *)p1 == *cast(char *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(char *)p1 - *cast(char *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return char.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        char t;
+
+        t = *cast(char *)p1;
+        *cast(char *)p1 = *cast(char *)p2;
+        *cast(char *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable char c;
+
+        return (cast(char *)&c)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_creal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,78 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_creal;
+
+// creal
+
+class TypeInfo_c : TypeInfo
+{
+    override string toString() { return "creal"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
+               (cast(uint *)p)[2] + (cast(uint *)p)[3] +
+               (cast(uint *)p)[4];
+    }
+
+    static equals_t _equals(creal f1, creal f2)
+    {
+        return f1 == f2;
+    }
+
+    static int _compare(creal f1, creal f2)
+    {   int result;
+
+        if (f1.re < f2.re)
+            result = -1;
+        else if (f1.re > f2.re)
+            result = 1;
+        else if (f1.im < f2.im)
+            result = -1;
+        else if (f1.im > f2.im)
+            result = 1;
+        else
+            result = 0;
+        return result;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(creal *)p1, *cast(creal *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(creal *)p1, *cast(creal *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return creal.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        creal t;
+
+        t = *cast(creal *)p1;
+        *cast(creal *)p1 = *cast(creal *)p2;
+        *cast(creal *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable creal r;
+
+        return (cast(creal *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_dchar.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,55 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_dchar;
+
+// dchar
+
+class TypeInfo_w : TypeInfo
+{
+    override string toString() { return "dchar"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(dchar *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(dchar *)p1 == *cast(dchar *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(dchar *)p1 - *cast(dchar *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return dchar.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        dchar t;
+
+        t = *cast(dchar *)p1;
+        *cast(dchar *)p1 = *cast(dchar *)p2;
+        *cast(dchar *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable dchar c;
+
+        return (cast(dchar *)&c)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_delegate.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,50 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_delegate;
+
+// delegate
+
+alias void delegate(int) dg;
+
+class TypeInfo_D : TypeInfo
+{
+    override hash_t getHash(in void* p)
+    {   long l = *cast(long *)p;
+
+        return cast(uint)(l + (l >> 32));
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(dg *)p1 == *cast(dg *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return dg.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        dg t;
+
+        t = *cast(dg *)p1;
+        *cast(dg *)p1 = *cast(dg *)p2;
+        *cast(dg *)p2 = t;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_double.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,75 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_double;
+
+// double
+
+class TypeInfo_d : TypeInfo
+{
+    override string toString() { return "double"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return (cast(uint *)p)[0] + (cast(uint *)p)[1];
+    }
+
+    static equals_t _equals(double f1, double f2)
+    {
+        return f1 == f2 ||
+                (f1 !<>= f1 && f2 !<>= f2);
+    }
+
+    static int _compare(double d1, double d2)
+    {
+        if (d1 !<>= d2)         // if either are NaN
+        {
+            if (d1 !<>= d1)
+            {   if (d2 !<>= d2)
+                    return 0;
+                return -1;
+            }
+            return 1;
+        }
+        return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(double *)p1, *cast(double *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(double *)p1, *cast(double *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return double.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        double t;
+
+        t = *cast(double *)p1;
+        *cast(double *)p1 = *cast(double *)p2;
+        *cast(double *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable double r;
+
+        return (cast(double *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_float.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,75 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_float;
+
+// float
+
+class TypeInfo_f : TypeInfo
+{
+    override string toString() { return "float"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(uint *)p;
+    }
+
+    static equals_t _equals(float f1, float f2)
+    {
+        return f1 == f2 ||
+                (f1 !<>= f1 && f2 !<>= f2);
+    }
+
+    static int _compare(float d1, float d2)
+    {
+        if (d1 !<>= d2)         // if either are NaN
+        {
+            if (d1 !<>= d1)
+            {   if (d2 !<>= d2)
+                    return 0;
+                return -1;
+            }
+            return 1;
+        }
+        return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(float *)p1, *cast(float *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(float *)p1, *cast(float *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return float.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        float t;
+
+        t = *cast(float *)p1;
+        *cast(float *)p1 = *cast(float *)p2;
+        *cast(float *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable float r;
+
+        return (cast(float *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_idouble.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,22 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_idouble;
+
+// idouble
+
+private import rt.typeinfo.ti_double;
+
+class TypeInfo_p : TypeInfo_d
+{
+    override string toString() { return "idouble"; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_ifloat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,22 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ifloat;
+
+// ifloat
+
+private import rt.typeinfo.ti_float;
+
+class TypeInfo_o : TypeInfo_f
+{
+    override string toString() { return "ifloat"; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_int.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,53 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_int;
+
+// int
+
+class TypeInfo_i : TypeInfo
+{
+    override string toString() { return "int"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(uint *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(uint *)p1 == *cast(uint *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        if (*cast(int*) p1 < *cast(int*) p2)
+            return -1;
+        else if (*cast(int*) p1 > *cast(int*) p2)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return int.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        int t;
+
+        t = *cast(int *)p1;
+        *cast(int *)p1 = *cast(int *)p2;
+        *cast(int *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_ireal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,22 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ireal;
+
+// ireal
+
+private import rt.typeinfo.ti_real;
+
+class TypeInfo_j : TypeInfo_e
+{
+    override string toString() { return "ireal"; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_long.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,53 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_long;
+
+// long
+
+class TypeInfo_l : TypeInfo
+{
+    override string toString() { return "long"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(uint *)p + (cast(uint *)p)[1];
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(long *)p1 == *cast(long *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        if (*cast(long *)p1 < *cast(long *)p2)
+            return -1;
+        else if (*cast(long *)p1 > *cast(long *)p2)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return long.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        long t;
+
+        t = *cast(long *)p1;
+        *cast(long *)p1 = *cast(long *)p2;
+        *cast(long *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_ptr.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,57 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ptr;
+
+// pointer
+
+class TypeInfo_P : TypeInfo
+{
+    override hash_t getHash(in void* p)
+    {
+        return cast(uint)*cast(void* *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(void* *)p1 == *cast(void* *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        auto c = *cast(void* *)p1 - *cast(void* *)p2;
+        if (c < 0)
+            return -1;
+        else if (c > 0)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (void*).sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        void* t;
+
+        t = *cast(void* *)p1;
+        *cast(void* *)p1 = *cast(void* *)p2;
+        *cast(void* *)p2 = t;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_real.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,75 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_real;
+
+// real
+
+class TypeInfo_e : TypeInfo
+{
+    override string toString() { return "real"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return (cast(uint *)p)[0] + (cast(uint *)p)[1] + (cast(ushort *)p)[4];
+    }
+
+    static equals_t _equals(real f1, real f2)
+    {
+        return f1 == f2 ||
+                (f1 !<>= f1 && f2 !<>= f2);
+    }
+
+    static int _compare(real d1, real d2)
+    {
+        if (d1 !<>= d2)         // if either are NaN
+        {
+            if (d1 !<>= d1)
+            {   if (d2 !<>= d2)
+                    return 0;
+                return -1;
+            }
+            return 1;
+        }
+        return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(real *)p1, *cast(real *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(real *)p1, *cast(real *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return real.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        real t;
+
+        t = *cast(real *)p1;
+        *cast(real *)p1 = *cast(real *)p2;
+        *cast(real *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable real r;
+
+        return (cast(real *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_short.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,49 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_short;
+
+// short
+
+class TypeInfo_s : TypeInfo
+{
+    override string toString() { return "short"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(short *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(short *)p1 == *cast(short *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(short *)p1 - *cast(short *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return short.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        short t;
+
+        t = *cast(short *)p1;
+        *cast(short *)p1 = *cast(short *)p2;
+        *cast(short *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_ubyte.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,54 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ubyte;
+
+// ubyte
+
+class TypeInfo_h : TypeInfo
+{
+    override string toString() { return "ubyte"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(ubyte *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(ubyte *)p1 == *cast(ubyte *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(ubyte *)p1 - *cast(ubyte *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return ubyte.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        ubyte t;
+
+        t = *cast(ubyte *)p1;
+        *cast(ubyte *)p1 = *cast(ubyte *)p2;
+        *cast(ubyte *)p2 = t;
+    }
+}
+
+class TypeInfo_b : TypeInfo_h
+{
+    override string toString() { return "bool"; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_uint.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,53 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_uint;
+
+// uint
+
+class TypeInfo_k : TypeInfo
+{
+    override string toString() { return "uint"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(uint *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(uint *)p1 == *cast(uint *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        if (*cast(uint*) p1 < *cast(uint*) p2)
+            return -1;
+        else if (*cast(uint*) p1 > *cast(uint*) p2)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return uint.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        int t;
+
+        t = *cast(uint *)p1;
+        *cast(uint *)p1 = *cast(uint *)p2;
+        *cast(uint *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_ulong.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,53 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ulong;
+
+// ulong
+
+class TypeInfo_m : TypeInfo
+{
+    override string toString() { return "ulong"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(uint *)p + (cast(uint *)p)[1];
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(ulong *)p1 == *cast(ulong *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        if (*cast(ulong *)p1 < *cast(ulong *)p2)
+            return -1;
+        else if (*cast(ulong *)p1 > *cast(ulong *)p2)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return ulong.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        ulong t;
+
+        t = *cast(ulong *)p1;
+        *cast(ulong *)p1 = *cast(ulong *)p2;
+        *cast(ulong *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_ushort.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,49 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ushort;
+
+// ushort
+
+class TypeInfo_t : TypeInfo
+{
+    override string toString() { return "ushort"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(ushort *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(ushort *)p1 == *cast(ushort *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(ushort *)p1 - *cast(ushort *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return ushort.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        ushort t;
+
+        t = *cast(ushort *)p1;
+        *cast(ushort *)p1 = *cast(ushort *)p2;
+        *cast(ushort *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_void.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,54 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_void;
+
+// void
+
+class TypeInfo_v : TypeInfo
+{
+    override string toString() { return "void"; }
+
+    override hash_t getHash(in void* p)
+    {
+        assert(0);
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(byte *)p1 == *cast(byte *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(byte *)p1 - *cast(byte *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return void.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        byte t;
+
+        t = *cast(byte *)p1;
+        *cast(byte *)p1 = *cast(byte *)p2;
+        *cast(byte *)p2 = t;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/typeinfo/ti_wchar.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,55 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_wchar;
+
+// wchar
+
+class TypeInfo_u : TypeInfo
+{
+    override string toString() { return "wchar"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(wchar *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(wchar *)p1 == *cast(wchar *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(wchar *)p1 - *cast(wchar *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return wchar.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        wchar t;
+
+        t = *cast(wchar *)p1;
+        *cast(wchar *)p1 = *cast(wchar *)p2;
+        *cast(wchar *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable wchar c;
+
+        return (cast(wchar *)&c)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/util/console.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,54 @@
+/**
+ * The console module contains some simple routines for console output.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.util.console;
+
+
+private
+{
+    version (Windows)
+    {
+        import core.sys.windows.windows;
+    }
+    else version( Posix )
+    {
+        import core.sys.posix.unistd;
+    }
+    import rt.util.string;
+}
+
+
+struct Console
+{
+    Console opCall( in char[] val )
+    {
+        version( Windows )
+        {
+            uint count = void;
+            WriteFile( GetStdHandle( 0xfffffff5 ), val.ptr, val.length, &count, null );
+        }
+        else version( Posix )
+        {
+            write( 2, val.ptr, val.length );
+        }
+        return this;
+    }
+
+
+    Console opCall( uint val )
+    {
+            char[10] tmp = void;
+            return opCall( tmp.intToString( val ) );
+    }
+}
+
+__gshared Console console;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/util/cpuid.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,719 @@
+/** 
+ * Identify the characteristics of the host CPU, providing information
+ * about cache sizes and assembly optimisation hints.
+ *
+ * Some of this information was extremely difficult to track down. Some of the
+ * documents below were found only in cached versions stored by search engines!
+ * This code relies on information found in:
+	
+ * - "Intel(R) 64 and IA-32 Architectures Software Developers Manual,
+ *	  Volume 2A: Instruction Set Reference, A-M" (2007).
+ * - "AMD CPUID Specification", Advanced Micro Devices, Rev 2.28 (2008).
+ * - "AMD Processor Recognition Application Note For Processors Prior to AMD
+ *    Family 0Fh Processors", Advanced Micro Devices, Rev 3.13 (2005).
+ * - "AMD Geode(TM) GX Processors Data Book",
+ *    Advanced Micro Devices, Publication ID 31505E, (2005).
+ * - "AMD K6 Processor Code Optimisation", Advanced Micro Devices, Rev D (2000).
+ * - "Application note 106: Software Customization for the 6x86 Family",
+ *    Cyrix Corporation, Rev 1.5 (1998)
+ * - http://ftp.intron.ac/pub/document/cpu/cpuid.htm
+ * - "Geode(TM) GX1 Processor Series Low Power Integrated X86 Solution",
+ *   National Semiconductor, (2002)
+ * - "The VIA Isaiah Architecture", G. Glenn Henry, Centaur Technology, Inc (2008).
+ * - http://www.sandpile.org/ia32/cpuid.htm
+ * - http://grafi.ii.pw.edu.pl/gbm/x86/cpuid.html
+ * - "What every programmer should know about memory",
+ *    Ulrich Depper, Red Hat, Inc., (2007). 
+ * 
+ * Bugs: Currently only works on x86 and Itanium CPUs.
+ *      Many processors have bugs in their microcode for the CPUID instruction,
+ *      so sometimes the cache information may be incorrect.
+ *
+ * Copyright: Copyright Don Clugston 2007 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Don Clugston, Tomas Lindquist Olsen &lt;tomas@famolsen.dk&gt;
+ *
+ *          Copyright Don Clugston 2007 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.util.cpuid;
+
+// If optimizing for a particular processor, it is generally better
+// to identify based on features rather than model. NOTE: Normally
+// it's only worthwhile to optimise for the latest Intel and AMD CPU,
+// with a backup for other CPUs.
+// Pentium    -- preferPentium1()
+// PMMX       --   + mmx()
+// PPro       -- default
+// PII        --   + mmx()
+// PIII       --   + mmx() + sse()
+// PentiumM   --   + mmx() + sse() + sse2()
+// Pentium4   -- preferPentium4()
+// PentiumD   --   + isX86_64()
+// Core2      -- default + isX86_64()
+// AMD K5     -- preferPentium1()
+// AMD K6     --   + mmx()
+// AMD K6-II  --   + mmx() + 3dnow()
+// AMD K7     -- preferAthlon()
+// AMD K8     --   + sse2()
+// AMD K10    --   + isX86_64()
+// Cyrix 6x86 -- preferPentium1()
+//    6x86MX  --   + mmx()
+
+public:
+
+/// Cache size and behaviour
+struct CacheInfo
+{
+    /// Size of the cache, in kilobytes, per CPU.
+    /// For L1 unified (data + code) caches, this size is half the physical size.
+    /// (we don't halve it for larger sizes, since normally
+    /// data size is much greater than code size for critical loops).
+	uint size;
+    /// Number of ways of associativity, eg:
+    /// 1 = direct mapped
+    /// 2 = 2-way set associative
+    /// 3 = 3-way set associative
+    /// ubyte.max = fully associative
+	ubyte associativity;
+    /// Number of bytes read into the cache when a cache miss occurs.
+	uint lineSize;
+}
+
+public:
+	/// Returns vendor string, for display purposes only.
+	/// Do NOT use this to determine features!
+	/// Note that some CPUs have programmable vendorIDs.
+	char[] vendor()		{return vendorID;}
+	/// Returns processor string, for display purposes only
+	char[] processor()	{return processorName;}    
+	
+	/// The data caches. If there are fewer than 5 physical caches levels,
+	/// the remaining levels are set to uint.max (== entire memory space)
+	__gshared CacheInfo[5] datacache;
+	/// Does it have an x87 FPU on-chip?
+	bool x87onChip()    {return (features&FPU_BIT)!=0;}
+    /// Is MMX supported?
+    bool mmx()			{return (features&MMX_BIT)!=0;}
+    /// Is SSE supported?
+    bool sse()			{return (features&SSE_BIT)!=0;}
+    /// Is SSE2 supported?
+    bool sse2()			{return (features&SSE2_BIT)!=0;}
+    /// Is SSE3 supported?
+    bool sse3()			{return (miscfeatures&SSE3_BIT)!=0;}
+    /// Is SSSE3 supported?
+    bool ssse3()		{return (miscfeatures&SSSE3_BIT)!=0;}
+    /// Is SSE4.1 supported?
+    bool sse41()		{return (miscfeatures&SSE41_BIT)!=0;}
+    /// Is SSE4.2 supported?
+    bool sse42()		{return (miscfeatures&SSE42_BIT)!=0;}
+    /// Is SSE4a supported?
+    bool sse4a()        {return (amdmiscfeatures&SSE4A_BIT)!=0;}
+    /// Is SSE5 supported?
+    bool sse5()			{return (amdmiscfeatures&SSE5_BIT)!=0;}
+    /// Is AMD 3DNOW supported?
+    bool amd3dnow()		{return (amdfeatures&AMD_3DNOW_BIT)!=0;}
+    /// Is AMD 3DNOW Ext supported?
+    bool amd3dnowExt()	{return (amdfeatures&AMD_3DNOW_EXT_BIT)!=0;}
+    /// Are AMD extensions to MMX supported?
+    bool amdMmx()		{return (amdfeatures&AMD_MMX_BIT)!=0;}
+    /// Is fxsave/fxrstor supported?
+    bool hasFxsr()			{return (features&FXSR_BIT)!=0;}
+    /// Is cmov supported?
+    bool hasCmov()			{return (features&CMOV_BIT)!=0;}
+    /// Is rdtsc supported?
+    bool hasRdtsc()			{return (features&TIMESTAMP_BIT)!=0;}
+    /// Is cmpxchg8b supported?
+    bool hasCmpxchg8b()		{return (features&CMPXCHG8B_BIT)!=0;}
+    /// Is cmpxchg8b supported?
+    bool hasCmpxchg16b()	{return (miscfeatures&CMPXCHG16B_BIT)!=0;}
+    /// Is 3DNow prefetch supported?
+    bool has3dnowPrefetch()
+    	{return (amdmiscfeatures&AMD_3DNOW_PREFETCH_BIT)!=0;}
+    /// Are LAHF and SAHF supported in 64-bit mode?
+    bool hasLahfSahf()			{return (amdmiscfeatures&LAHFSAHF_BIT)!=0;}
+    /// Is POPCNT supported?
+    bool hasPopcnt()		{return (miscfeatures&POPCNT_BIT)!=0;}    
+    /// Is LZCNT supported?
+    bool hasLzcnt()			{return (amdmiscfeatures&LZCNT_BIT)!=0;}
+    /// Is this an Intel64 or AMD 64?
+    bool isX86_64()			{return (amdfeatures&AMD64_BIT)!=0;}
+            
+    /// Is this an IA64 (Itanium) processor?
+    bool isItanium()        { return (features&IA64_BIT)!=0; }
+
+    /// Is hyperthreading supported?
+    bool hyperThreading()   { return maxThreads>maxCores; }
+    /// Returns number of threads per CPU
+    uint threadsPerCPU()	{return maxThreads;}
+    /// Returns number of cores in CPU
+    uint coresPerCPU()		{return maxCores;}
+    
+    /// Optimisation hints for assembly code.
+    /// For forward compatibility, the CPU is compared against different
+    /// microarchitectures. For 32-bit X86, comparisons are made against
+    /// the Intel PPro/PII/PIII/PM family.
+    ///
+    /// The major 32-bit x86 microarchitecture 'dynasties' have been:
+    /// (1) Intel P6 (PentiumPro, PII, PIII, PM, Core, Core2).
+    /// (2) AMD Athlon (K7, K8, K10).
+    /// (3) Intel NetBurst (Pentium 4, Pentium D).
+    /// (4) In-order Pentium (Pentium1, PMMX)
+    /// Other early CPUs (Nx586, AMD K5, K6, Centaur C3, Transmeta,
+    ///   Cyrix, Rise) were mostly in-order.
+    /// Some new processors do not fit into the existing categories:
+    /// Intel Atom 230/330 (family 6, model 0x1C) is an in-order core.
+    /// Centaur Isiah = VIA Nano (family 6, model F) is an out-of-order core.
+    ///
+    /// Within each dynasty, the optimisation techniques are largely
+    /// identical (eg, use instruction pairing for group 4). Major
+    /// instruction set improvements occur within each group.
+    
+    /// Does this CPU perform better on AMD K7 code than PentiumPro..Core2 code?
+    bool preferAthlon() { return probablyAMD && family >=6; }
+    /// Does this CPU perform better on Pentium4 code than PentiumPro..Core2 code?
+    bool preferPentium4() { return probablyIntel && family == 0xF; }
+    /// Does this CPU perform better on Pentium I code than Pentium Pro code?
+    bool preferPentium1() { return family < 6 || (family==6 && model < 0xF && !probablyIntel); }
+
+__gshared:
+public:
+    /// Processor type (vendor-dependent).
+    /// This should be visible ONLY for display purposes.
+    uint stepping, model, family;
+    uint numCacheLevels = 1;
+private:
+	bool probablyIntel; // true = _probably_ an Intel processor, might be faking
+	bool probablyAMD; // true = _probably_ an AMD processor
+	char [12] vendorID;
+	char [] processorName;
+	char [48] processorNameBuffer;
+	uint features = 0;     // mmx, sse, sse2, hyperthreading, etc
+	uint miscfeatures = 0; // sse3, etc.
+	uint amdfeatures = 0;  // 3DNow!, mmxext, etc
+	uint amdmiscfeatures = 0; // sse4a, sse5, svm, etc
+	uint maxCores = 1;
+	uint maxThreads = 1;
+	// Note that this may indicate multi-core rather than hyperthreading.
+    bool hyperThreadingBit()	{ return (features&HTT_BIT)!=0;}
+    
+    // feature flags CPUID1_EDX
+    enum : uint
+    {
+    	FPU_BIT = 1,
+	    TIMESTAMP_BIT = 1<<4, // rdtsc
+	    MDSR_BIT = 1<<5,      // RDMSR/WRMSR
+	    CMPXCHG8B_BIT = 1<<8,
+    	    CMOV_BIT = 1<<15,
+	    MMX_BIT = 1<<23,
+	    FXSR_BIT = 1<<24,
+	    SSE_BIT = 1<<25,
+	    SSE2_BIT = 1<<26,
+	    HTT_BIT = 1<<28,
+	    IA64_BIT = 1<<30
+    }
+    // feature flags misc CPUID1_ECX
+    enum : uint
+    {
+	    SSE3_BIT = 1,
+            PCLMULQDQ_BIT = 1<<1, // from AVX
+	    MWAIT_BIT = 1<<3,
+	    SSSE3_BIT = 1<<9,
+            FMA_BIT = 1<<12,     // from AVX
+	    CMPXCHG16B_BIT = 1<<13,
+	    SSE41_BIT = 1<<19,
+	    SSE42_BIT = 1<<20,
+	    POPCNT_BIT = 1<<23,
+            AES_BIT = 1<<25, // AES instructions from AVX
+            OSXSAVE_BIT = 1<<27, // Used for AVX
+            AVX_BIT = 1<<28
+    }
+/+    
+version(X86_64) {    
+    bool hasAVXinHardware() {
+        // This only indicates hardware support, not OS support.
+        return (miscfeatures&AVX_BIT) && (miscfeatures&OSXSAVE_BIT);
+    }
+    // Is AVX supported (in both hardware & OS)?
+    bool Avx() {
+        if (!hasAVXinHardware()) return false;
+        // Check for OS support
+        uint xfeatures;
+        asm {mov ECX, 0; xgetbv; mov xfeatures, EAX; }
+        return (xfeatures&0x6)==6;
+    }
+    bool hasAvxFma() {
+        if (!AVX()) return false;
+        return (features&FMA_BIT)!=0;        
+    }
+}
++/    
+    // AMD feature flags CPUID80000001_EDX
+    enum : uint
+    {
+	    AMD_MMX_BIT = 1<<22,
+//	    FXR_OR_CYRIXMMX_BIT = 1<<24, // Cyrix/NS: 6x86MMX instructions. 
+	    FFXSR_BIT = 1<<25,
+	    PAGE1GB_BIT = 1<<26, // support for 1GB pages
+	    RDTSCP_BIT = 1<<27,
+	    AMD64_BIT = 1<<29,
+	    AMD_3DNOW_EXT_BIT = 1<<30,
+	    AMD_3DNOW_BIT = 1<<31
+    }
+    // AMD misc feature flags CPUID80000001_ECX
+    enum : uint
+    {
+    	LAHFSAHF_BIT = 1,
+    	LZCNT_BIT = 1<<5,
+    	SSE4A_BIT = 1<<6,    	
+    	AMD_3DNOW_PREFETCH_BIT = 1<<8,
+    	SSE5_BIT = 1<<11
+    }
+
+version(GNU){
+    // GDC is a filthy liar. It can't actually do inline asm.
+} else version(D_InlineAsm_X86) {
+    version = Really_D_InlineAsm_X86;
+}
+
+version(Really_D_InlineAsm_X86) {
+// Note that this code will also work for Itanium in x86 mode.
+
+shared uint max_cpuid, max_extended_cpuid;
+
+// CPUID2: "cache and tlb information"
+void getcacheinfoCPUID2()
+{
+	// We are only interested in the data caches
+	void decipherCpuid2(ubyte x) {
+		if (x==0) return;
+		// Values from http://www.sandpile.org/ia32/cpuid.htm.
+		// Includes Itanium and non-Intel CPUs.
+		//
+		immutable ubyte [47] ids = [
+			0x0A, 0x0C, 0x2C, 0x60, 0x0E, 0x66, 0x67, 0x68,
+			// level 2 cache
+			0x41, 0x42, 0x43, 0x44, 0x45, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7F,
+		    0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x49, 0x4E,
+		    0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x48, 0x80, 0x81,
+		    // level 3 cache
+			0x22, 0x23, 0x25, 0x29, 0x46, 0x47, 0x4A, 0x4B, 0x4C, 0x4D
+		];
+		immutable uint [47] sizes = [
+			8, 16, 32, 16, 24, 8, 16, 32,
+		    128, 256, 512, 1024, 2048, 1024, 128, 256, 512, 1024, 2048, 512,
+		    256, 512, 1024, 2048, 512, 1024, 4096, 6*1024,
+		    128, 192, 128, 256, 384, 512, 3072, 512, 128,		    
+			512, 1024, 2048, 4096, 4096, 8192, 6*1024, 8192, 12*1024, 16*1024
+		];
+	// CPUBUG: Pentium M reports 0x2C but tests show it is only 4-way associative
+		immutable ubyte [47] ways = [
+			2, 4, 8, 8, 6, 4, 4, 4,
+		    4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 2,
+		    8, 8, 8, 8, 4, 8, 16, 24,
+		    4, 6, 2, 4, 6, 4, 12, 8, 8,
+			4, 8, 8, 8, 4, 8, 12, 16, 12, 16
+		];
+		enum { FIRSTDATA2 = 8, FIRSTDATA3 = 28+9 }
+		for (int i=0; i< ids.length; ++i) {
+			if (x==ids[i]) {
+				int level = i< FIRSTDATA2 ? 0: i<FIRSTDATA3 ? 1 : 2;
+				if (x==0x49 && family==0xF && model==0x6) level=2;
+				datacache[level].size=sizes[i];
+				datacache[level].associativity=ways[i];
+				if (level == 3 || x==0x2C || (x>=0x48 && x<=0x80) 
+                                   || x==0x86 || x==0x87
+                                   || (x>=0x66 && x<=0x68) || (x>=0x39 && x<=0x3E)){
+					datacache[level].lineSize = 64;
+				} else datacache[level].lineSize = 32;
+			}
+		}
+	}
+
+	uint[4] a;	
+	bool firstTime = true;
+	// On a multi-core system, this could theoretically fail, but it's only used
+	// for old single-core CPUs.
+	uint numinfos = 1;
+	do {
+		asm {
+			mov EAX, 2;
+			cpuid;
+			mov a, EAX;
+			mov a+4, EBX;
+			mov a+8, ECX;
+			mov a+12, EDX;
+		}
+		if (firstTime) {
+			if (a[0]==0x0000_7001 && a[3]==0x80 && a[1]==0 && a[2]==0) {
+		// Cyrix MediaGX MMXEnhanced returns: EAX= 00007001, EDX=00000080.
+		// These are NOT standard Intel values
+		// (TLB = 32 entry, 4 way associative, 4K pages)
+		// (L1 cache = 16K, 4way, linesize16)
+				datacache[0].size=8;
+				datacache[0].associativity=4;
+				datacache[0].lineSize=16;
+				return;				
+			}
+			// lsb of a is how many times to loop.
+			numinfos = a[0] & 0xFF;
+			// and otherwise it should be ignored
+			a[0] &= 0xFFFF_FF00;
+			firstTime = false;
+		}
+		for (int c=0; c<4;++c) {
+			// high bit set == no info.
+			if (a[c] & 0x8000_0000) continue;
+			decipherCpuid2(cast(ubyte)(a[c] & 0xFF));
+			decipherCpuid2(cast(ubyte)((a[c]>>8) & 0xFF));
+			decipherCpuid2(cast(ubyte)((a[c]>>16) & 0xFF));
+			decipherCpuid2(cast(ubyte)((a[c]>>24) & 0xFF));
+		}
+	} while (--numinfos);
+}
+
+// CPUID4: "Deterministic cache parameters" leaf
+void getcacheinfoCPUID4()
+{
+	int cachenum = 0;
+	for(;;) {
+		uint a, b, number_of_sets;	
+		asm {
+			mov EAX, 4;
+			mov ECX, cachenum;
+			cpuid;
+			mov a, EAX;
+			mov b, EBX;
+			mov number_of_sets, ECX;
+		}
+		++cachenum;
+		if ((a&0x1F)==0) break; // no more caches
+		uint numthreads = ((a>>14) & 0xFFF)  + 1;
+		uint numcores = ((a>>26) & 0x3F) + 1;
+		if (numcores > maxCores) maxCores = numcores;
+		if ((a&0x1F)!=1 && ((a&0x1F)!=3)) continue; // we only want data & unified caches
+		
+		++number_of_sets;
+		ubyte level = cast(ubyte)(((a>>5)&7)-1);
+		if (level > datacache.length) continue; // ignore deep caches
+		datacache[level].associativity = a & 0x200 ? ubyte.max :cast(ubyte)((b>>22)+1);
+		datacache[level].lineSize = (b & 0xFFF)+ 1; // system coherency line size
+		uint line_partitions = ((b >> 12)& 0x3FF) + 1;
+		// Size = number of sets * associativity * cachelinesize * linepartitions
+		// and must convert to Kb, also dividing by the number of hyperthreads using this cache.
+		ulong sz = (datacache[level].associativity< ubyte.max)? number_of_sets *
+			datacache[level].associativity : number_of_sets;		
+		datacache[level].size = cast(uint)(
+				(sz * datacache[level].lineSize * line_partitions ) / (numthreads *1024));
+		if (level == 0 && (a&0xF)==3) {
+			// Halve the size for unified L1 caches
+			datacache[level].size/=2;
+		}
+	}
+}
+
+// CPUID8000_0005 & 6
+void getAMDcacheinfo()
+{
+	uint c5, c6, d6;
+	asm {
+		mov EAX, 0x8000_0005; // L1 cache
+		cpuid;
+		// EAX has L1_TLB_4M.
+		// EBX has L1_TLB_4K
+		// EDX has L1 instruction cache
+		mov c5, ECX;
+	}
+
+	datacache[0].size = ( (c5>>24) & 0xFF);
+	datacache[0].associativity = cast(ubyte)( (c5 >> 16) & 0xFF);
+	datacache[0].lineSize = c5 & 0xFF;
+
+	if (max_extended_cpuid >= 0x8000_0006) {
+		// AMD K6-III or K6-2+ or later.
+		ubyte numcores = 1;
+		if (max_extended_cpuid >=0x8000_0008) {
+			asm {
+		    	mov EAX, 0x8000_0008;
+		    	cpuid;
+		    	mov numcores, CL;
+		    }
+		    ++numcores;
+		    if (numcores>maxCores) maxCores = numcores;
+		}
+		asm {
+			mov EAX, 0x8000_0006; // L2/L3 cache
+			cpuid;
+			mov c6, ECX; // L2 cache info
+			mov d6, EDX; // L3 cache info
+		}
+	
+		immutable ubyte [] assocmap = [ 0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 96, 128, 0xFF ];
+		datacache[1].size = (c6>>16) & 0xFFFF;
+		datacache[1].associativity = assocmap[(c6>>12)&0xF];
+		datacache[1].lineSize = c6 & 0xFF;
+		
+		// The L3 cache value is TOTAL, not per core.
+		datacache[2].size = ((d6>>18)*512)/numcores; // could be up to 2 * this, -1.
+		datacache[2].associativity = assocmap[(d6>>12)&0xF];
+		datacache[2].lineSize = d6 & 0xFF;
+	}
+}
+
+
+void cpuidX86()
+{
+    char * venptr = vendorID.ptr;
+	asm {
+		mov EAX, 0;
+		cpuid;
+		mov max_cpuid, EAX;
+		mov EAX, venptr;
+		mov [EAX], EBX;
+		mov [EAX + 4], EDX;
+		mov [EAX + 8], ECX;
+		mov EAX, 0x8000_0000;
+		cpuid;
+		mov max_extended_cpuid, EAX;
+	}
+	
+	probablyIntel = vendorID == "GenuineIntel";
+	probablyAMD = vendorID == "AuthenticAMD";
+	uint a, b, c, d;
+	uint apic = 0; // brand index, apic id
+	asm {
+		mov EAX, 1; // model, stepping
+		cpuid;
+		mov a, EAX;
+		mov apic, EBX;
+		mov miscfeatures, ECX;
+		mov features, EDX;
+	}
+	amdfeatures = 0;
+	amdmiscfeatures = 0;
+	if (max_extended_cpuid >= 0x8000_0001) {
+		asm {
+			mov EAX, 0x8000_0001;
+			cpuid;
+			mov amdmiscfeatures, ECX;
+			mov amdfeatures, EDX;
+		}
+	}
+	// Try to detect fraudulent vendorIDs
+	if (amd3dnow) probablyIntel = false;
+	
+	stepping = a & 0xF;
+	uint fbase = (a >> 8) & 0xF;
+	uint mbase = (a >> 4) & 0xF;
+	family = ((fbase == 0xF) || (fbase == 0)) ? fbase + (a >> 20) & 0xFF : fbase;
+	model = ((fbase == 0xF) || (fbase == 6 && probablyIntel) ) ?
+	     mbase + ((a >> 12) & 0xF0) : mbase;
+	     
+	if (!probablyIntel && max_extended_cpuid >= 0x8000_0008) {
+		// determine max number of cores for AMD
+		asm {
+			mov EAX, 0x8000_0008;
+			cpuid;
+			mov c, ECX;
+		}
+		uint apicsize = (c>>12) & 0xF;
+		if (apicsize == 0) {
+			// use legacy method
+			if (hyperThreadingBit)	maxCores = c & 0xFF;
+			else maxCores = 1;
+		} else {
+			// maxcores = 2^ apicsize
+			maxCores = 1;
+			while (apicsize) { maxCores<<=1; --apicsize; }
+		}
+	}
+	
+	if (max_extended_cpuid >= 0x8000_0004) {
+		char *procptr = processorNameBuffer.ptr;
+		asm {
+			push ESI;
+			mov ESI, procptr;
+			mov EAX, 0x8000_0002;
+			cpuid;
+			mov [ESI], EAX;
+			mov [ESI+4], EBX;
+			mov [ESI+8], ECX;
+			mov [ESI+12], EDX;
+			mov EAX, 0x8000_0003;
+			cpuid;
+			mov [ESI+16], EAX;
+			mov [ESI+20], EBX;
+			mov [ESI+24], ECX;
+			mov [ESI+28], EDX;
+			mov EAX, 0x8000_0004;
+			cpuid;
+			mov [ESI+32], EAX;
+			mov [ESI+36], EBX;
+			mov [ESI+40], ECX;
+			mov [ESI+44], EDX;
+			pop ESI;			
+		}
+		// Intel P4 and PM pad at front with spaces.
+		// Other CPUs pad at end with nulls.
+		int start = 0, end = 0;
+		while (processorNameBuffer[start] == ' ') { ++start; }
+		while (processorNameBuffer[$-end-1] == 0) { ++end; }
+		processorName = processorNameBuffer[start..$-end];
+	} else {
+		processorName[] = "Unknown CPU";
+	}
+	// Determine cache sizes
+	
+	// Intel docs specify that they return 0 for 0x8000_0005.
+	// AMD docs do not specify the behaviour for 0004 and 0002.
+	// Centaur/VIA and most other manufacturers use the AMD method,
+	// except Cyrix MediaGX MMX Enhanced uses their OWN form of CPUID2!
+	// NS Geode GX1 provides CyrixCPUID2 _and_ does the same wrong behaviour
+	// for CPUID80000005. But Geode GX uses the AMD method
+	
+	// Deal with Geode GX1 - make it same as MediaGX MMX.
+	if (max_extended_cpuid==0x8000_0005 && max_cpuid==2) {		
+		max_extended_cpuid = 0x8000_0004;
+	}
+	// Therefore, we try the AMD method unless it's an Intel chip.
+	// If we still have no info, try the Intel methods.
+	datacache[0].size = 0;
+	if (max_cpuid<2 || !probablyIntel) {
+		if (max_extended_cpuid >= 0x8000_0005) {
+			getAMDcacheinfo();
+		} else if (probablyAMD) {		
+			// According to AMDProcRecognitionAppNote, this means CPU
+			// K5 model 0, or Am5x86 (model 4), or Am4x86DX4 (model 4)
+			// Am5x86 has 16Kb 4-way unified data & code cache.
+			datacache[0].size = 8;
+			datacache[0].associativity = 4;
+			datacache[0].lineSize = 32;		
+		} else {
+			// Some obscure CPU.
+			// Values for Cyrix 6x86MX (family 6, model 0)
+			datacache[0].size = 64;
+			datacache[0].associativity = 4;
+			datacache[0].lineSize = 32;		
+		}
+	}	
+	if ((datacache[0].size == 0) && max_cpuid>=4) {
+		getcacheinfoCPUID4();
+	}
+	if ((datacache[0].size == 0) && max_cpuid>=2) {		
+		getcacheinfoCPUID2();
+	}
+	if (datacache[0].size == 0) {
+		// Pentium, PMMX, late model 486, or an obscure CPU
+		if (mmx) { // Pentium MMX. Also has 8kB code cache.
+			datacache[0].size = 16;
+			datacache[0].associativity = 4;
+			datacache[0].lineSize = 32;		
+		} else { // Pentium 1 (which also has 8kB code cache)
+				 // or 486.
+			// Cyrix 6x86: 16, 4way, 32 linesize
+			datacache[0].size = 8;
+			datacache[0].associativity = 2;
+			datacache[0].lineSize = 32;
+		}		
+	}
+	if (hyperThreadingBit) maxThreads = (apic>>>16) & 0xFF;
+	else maxThreads = maxCores;
+}
+
+// Return true if the cpuid instruction is supported.
+// BUG(WONTFIX): Returns false for Cyrix 6x86 and 6x86L. They will be treated as 486 machines.
+bool hasCPUID()
+{
+	uint flags;
+	asm {
+		pushfd;
+		pop EAX;
+		mov flags, EAX;
+		xor EAX, 0x0020_0000;
+		push EAX;
+		popfd;
+		pushfd;
+		pop EAX;
+		xor flags, EAX;
+	}
+	return (flags & 0x0020_0000) !=0;
+}
+
+} else { // inline asm X86
+
+	bool hasCPUID() { return false; }
+
+	void cpuidX86()
+	{
+			datacache[0].size = 8;
+			datacache[0].associativity = 2;
+			datacache[0].lineSize = 32;		
+	}	
+}
+
+// TODO: Implement this function with OS support
+void cpuidPPC()
+{
+	enum :int  { PPC601, PPC603, PPC603E, PPC604,
+	             PPC604E, PPC620, PPCG3, PPCG4, PPCG5 };
+
+	// TODO:
+	// asm { mfpvr; } returns the CPU version but unfortunately it can
+	// only be used in kernel mode. So OS support is required.
+	int cputype = PPC603;
+	
+	// 601 has a 8KB combined data & code L1 cache.
+	uint sizes[] = [4, 8, 16, 16, 32, 32, 32, 32, 64];
+	ubyte ways[] = [8, 2,  4,  4,  4,  8,  8,  8,  8];
+	uint L2size[]= [0, 0,  0,  0,  0,  0,  0,  256,  512];
+	uint L3size[]= [0, 0,  0,  0,  0,  0,  0,  2048,  0];
+    
+	datacache[0].size = sizes[cputype];
+	datacache[0].associativity = ways[cputype]; 
+	datacache[0].lineSize = (cputype==PPCG5)? 128 : 
+		(cputype == PPC620 || cputype == PPCG3)? 64 : 32;
+	datacache[1].size = L2size[cputype];
+	datacache[2].size = L3size[cputype];
+	datacache[1].lineSize = datacache[0].lineSize;
+	datacache[2].lineSize = datacache[0].lineSize;
+}
+
+// TODO: Implement this function with OS support
+void cpuidSparc()
+{
+	// UltaSparcIIi  : L1 = 16,  2way. L2 = 512, 4 way.
+	// UltraSparcIII : L1 = 64,  4way. L2= 4096 or 8192.
+	// UltraSparcIIIi: L1 = 64,  4way. L2= 1024, 4 way
+	// UltraSparcIV  : L1 = 64,  4way. L2 = 16*1024.
+	// UltraSparcIV+ : L1 = 64,  4way. L2 = 2048, L3=32*1024.
+	// Sparc64V      : L1 = 128, 2way. L2 = 4096 4way.	
+}
+
+
+static this()
+{
+	if (hasCPUID()) {
+		cpuidX86();
+	} else {
+		// it's a 386 or 486, or a Cyrix 6x86.
+		//Probably still has an external cache.
+	}
+	if (datacache[0].size==0) {
+			// Guess same as Pentium 1.
+			datacache[0].size = 8;
+			datacache[0].associativity = 2;
+			datacache[0].lineSize = 32;		
+	}
+	numCacheLevels = 1;
+	// And now fill up all the unused levels with full memory space.
+	for (int i=1; i< datacache.length; ++i) {
+		if (datacache[i].size==0) {
+			// Set all remaining levels of cache equal to full address space.
+			datacache[i].size = uint.max/1024;
+			datacache[i].associativity = 1;
+			datacache[i].lineSize = datacache[i-1].lineSize;
+		} else numCacheLevels = i+1;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/util/ctype.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,92 @@
+/**
+ * Simple ASCII char classification functions.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.util.ctype;
+
+int isalnum(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG) : 0; }
+int isalpha(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP)      : 0; }
+int iscntrl(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_CTL)      : 0; }
+int isdigit(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_DIG)      : 0; }
+int islower(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_LC)       : 0; }
+int ispunct(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_PNC)      : 0; }
+int isspace(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_SPC)      : 0; }
+int isupper(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_UC)       : 0; }
+int isxdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_HEX)      : 0; }
+int isgraph(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC) : 0; }
+int isprint(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC|_BLK) : 0; }
+int isascii(dchar c)  { return c <= 0x7F; }
+
+dchar tolower(dchar c)
+out (result)
+{
+    assert(!isupper(result));
+}
+body
+{
+    return isupper(c) ? c + (cast(dchar)'a' - 'A') : c;
+}
+
+dchar toupper(dchar c)
+out (result)
+{
+    assert(!islower(result));
+}
+body
+{
+    return islower(c) ? c - (cast(dchar)'a' - 'A') : c;
+}
+
+private:
+
+enum
+{
+    _SPC =	8,
+    _CTL =	0x20,
+    _BLK =	0x40,
+    _HEX =	0x80,
+    _UC  =	1,
+    _LC  =	2,
+    _PNC =	0x10,
+    _DIG =	4,
+    _ALP =	_UC|_LC,
+}
+
+immutable ubyte _ctype[128] =
+[
+	_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
+	_CTL,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL,_CTL,
+	_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
+	_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
+	_SPC|_BLK,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
+	_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
+	_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_PNC,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC,
+	_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
+	_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
+	_UC,_UC,_UC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_PNC,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC,
+	_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
+	_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
+	_LC,_LC,_LC,_PNC,_PNC,_PNC,_PNC,_CTL
+];
+
+
+unittest
+{
+    assert(isspace(' '));
+    assert(!isspace('z'));
+    assert(toupper('a') == 'A');
+    assert(tolower('Q') == 'q');
+    assert(!isxdigit('G'));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/util/string.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,40 @@
+/**
+ * The exception module defines all system-level exceptions and provides a
+ * mechanism to alter system-level error handling.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.util.string;
+
+private import core.stdc.string;
+
+char[] intToString( char[] buf, uint val )
+{
+    assert( buf.length > 9 );
+    auto p = buf.ptr + buf.length;
+
+    do
+    {
+        *--p = cast(char)(val % 10 + '0');
+    } while( val /= 10 );
+
+    return buf[p - buf.ptr .. $];
+}
+
+
+int dstrcmp( in char[] s1, in char[] s2 )
+{
+    auto len = s1.length;
+    if( s2.length < len )
+        len = s2.length;
+    if( memcmp( s1.ptr, s2.ptr, len ) == 0 )
+        return 0;
+    return s1.length > s2.length ? 1 : -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/util/utf.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,901 @@
+/********************************************
+ * Encode and decode UTF-8, UTF-16 and UTF-32 strings.
+ *
+ * For Win32 systems, the C wchar_t type is UTF-16 and corresponds to the D
+ * wchar type.
+ * For Posix systems, the C wchar_t type is UTF-32 and corresponds to
+ * the D utf.dchar type.
+ *
+ * UTF character support is restricted to (\u0000 &lt;= character &lt;= \U0010FFFF).
+ *
+ * See_Also:
+ *	$(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia)<br>
+ *	$(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)<br>
+ *	$(LINK http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335)
+ * Macros:
+ *	WIKI = Phobos/StdUtf
+ *
+ * Copyright: Copyright Digital Mars 2003 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2003 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.util.utf;
+
+
+extern (C) void onUnicodeError( string msg, size_t idx );
+
+/*******************************
+ * Test if c is a valid UTF-32 character.
+ *
+ * \uFFFE and \uFFFF are considered valid by this function,
+ * as they are permitted for internal use by an application,
+ * but they are not allowed for interchange by the Unicode standard.
+ *
+ * Returns: true if it is, false if not.
+ */
+
+bool isValidDchar(dchar c)
+{
+    /* Note: FFFE and FFFF are specifically permitted by the
+     * Unicode standard for application internal use, but are not
+     * allowed for interchange.
+     * (thanks to Arcane Jill)
+     */
+
+    return c < 0xD800 ||
+	(c > 0xDFFF && c <= 0x10FFFF /*&& c != 0xFFFE && c != 0xFFFF*/);
+}
+
+unittest
+{
+    debug(utf) printf("utf.isValidDchar.unittest\n");
+    assert(isValidDchar(cast(dchar)'a') == true);
+    assert(isValidDchar(cast(dchar)0x1FFFFF) == false);
+}
+
+
+
+immutable UTF8stride =
+[
+    cast(ubyte)
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+    4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF,
+];
+
+/**
+ * stride() returns the length of a UTF-8 sequence starting at index i
+ * in string s.
+ * Returns:
+ *	The number of bytes in the UTF-8 sequence or
+ *	0xFF meaning s[i] is not the start of of UTF-8 sequence.
+ */
+uint stride(in char[] s, size_t i)
+{
+    return UTF8stride[s[i]];
+}
+
+/**
+ * stride() returns the length of a UTF-16 sequence starting at index i
+ * in string s.
+ */
+uint stride(in wchar[] s, size_t i)
+{   uint u = s[i];
+    return 1 + (u >= 0xD800 && u <= 0xDBFF);
+}
+
+/**
+ * stride() returns the length of a UTF-32 sequence starting at index i
+ * in string s.
+ * Returns: The return value will always be 1.
+ */
+uint stride(in dchar[] s, size_t i)
+{
+    return 1;
+}
+
+/*******************************************
+ * Given an index i into an array of characters s[],
+ * and assuming that index i is at the start of a UTF character,
+ * determine the number of UCS characters up to that index i.
+ */
+
+size_t toUCSindex(in char[] s, size_t i)
+{
+    size_t n;
+    size_t j;
+
+    for (j = 0; j < i; )
+    {
+	j += stride(s, j);
+	n++;
+    }
+    if (j > i)
+    {
+        onUnicodeError("invalid UTF-8 sequence", j);
+    }
+    return n;
+}
+
+/** ditto */
+size_t toUCSindex(in wchar[] s, size_t i)
+{
+    size_t n;
+    size_t j;
+
+    for (j = 0; j < i; )
+    {
+	j += stride(s, j);
+	n++;
+    }
+    if (j > i)
+    {
+        onUnicodeError("invalid UTF-16 sequence", j);
+    }
+    return n;
+}
+
+/** ditto */
+size_t toUCSindex(in dchar[] s, size_t i)
+{
+    return i;
+}
+
+/******************************************
+ * Given a UCS index n into an array of characters s[], return the UTF index.
+ */
+
+size_t toUTFindex(in char[] s, size_t n)
+{
+    size_t i;
+
+    while (n--)
+    {
+	uint j = UTF8stride[s[i]];
+	if (j == 0xFF)
+	    onUnicodeError("invalid UTF-8 sequence", i);
+	i += j;
+    }
+    return i;
+}
+
+/** ditto */
+size_t toUTFindex(in wchar[] s, size_t n)
+{
+    size_t i;
+
+    while (n--)
+    {	wchar u = s[i];
+
+	i += 1 + (u >= 0xD800 && u <= 0xDBFF);
+    }
+    return i;
+}
+
+/** ditto */
+size_t toUTFindex(in dchar[] s, size_t n)
+{
+    return n;
+}
+
+/* =================== Decode ======================= */
+
+/***************
+ * Decodes and returns character starting at s[idx]. idx is advanced past the
+ * decoded character. If the character is not well formed, a UtfException is
+ * thrown and idx remains unchanged.
+ */
+dchar decode(in char[] s, inout size_t idx)
+    in
+    {
+	assert(idx >= 0 && idx < s.length);
+    }
+    out (result)
+    {
+	assert(isValidDchar(result));
+    }
+    body
+    {
+	size_t len = s.length;
+	dchar V;
+	size_t i = idx;
+	char u = s[i];
+
+	if (u & 0x80)
+	{   uint n;
+	    char u2;
+
+	    /* The following encodings are valid, except for the 5 and 6 byte
+	     * combinations:
+	     *	0xxxxxxx
+	     *	110xxxxx 10xxxxxx
+	     *	1110xxxx 10xxxxxx 10xxxxxx
+	     *	11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+	     *	111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+	     *	1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+	     */
+	    for (n = 1; ; n++)
+	    {
+		if (n > 4)
+		    goto Lerr;		// only do the first 4 of 6 encodings
+		if (((u << n) & 0x80) == 0)
+		{
+		    if (n == 1)
+			goto Lerr;
+		    break;
+		}
+	    }
+
+	    // Pick off (7 - n) significant bits of B from first byte of octet
+	    V = cast(dchar)(u & ((1 << (7 - n)) - 1));
+
+	    if (i + (n - 1) >= len)
+		goto Lerr;			// off end of string
+
+	    /* The following combinations are overlong, and illegal:
+	     *	1100000x (10xxxxxx)
+	     *	11100000 100xxxxx (10xxxxxx)
+	     *	11110000 1000xxxx (10xxxxxx 10xxxxxx)
+	     *	11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
+	     *	11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
+	     */
+	    u2 = s[i + 1];
+	    if ((u & 0xFE) == 0xC0 ||
+		(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
+		(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
+		(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
+		(u == 0xFC && (u2 & 0xFC) == 0x80))
+		goto Lerr;			// overlong combination
+
+	    for (uint j = 1; j != n; j++)
+	    {
+		u = s[i + j];
+		if ((u & 0xC0) != 0x80)
+		    goto Lerr;			// trailing bytes are 10xxxxxx
+		V = (V << 6) | (u & 0x3F);
+	    }
+	    if (!isValidDchar(V))
+		goto Lerr;
+	    i += n;
+	}
+	else
+	{
+	    V = cast(dchar) u;
+	    i++;
+	}
+
+	idx = i;
+	return V;
+
+      Lerr:
+      onUnicodeError("invalid UTF-8 sequence", i);
+    return V; // dummy return
+    }
+
+unittest
+{   size_t i;
+    dchar c;
+
+    debug(utf) printf("utf.decode.unittest\n");
+
+    static s1 = "abcd"c;
+    i = 0;
+    c = decode(s1, i);
+    assert(c == cast(dchar)'a');
+    assert(i == 1);
+    c = decode(s1, i);
+    assert(c == cast(dchar)'b');
+    assert(i == 2);
+
+    static s2 = "\xC2\xA9"c;
+    i = 0;
+    c = decode(s2, i);
+    assert(c == cast(dchar)'\u00A9');
+    assert(i == 2);
+
+    static s3 = "\xE2\x89\xA0"c;
+    i = 0;
+    c = decode(s3, i);
+    assert(c == cast(dchar)'\u2260');
+    assert(i == 3);
+
+    static s4 =
+    [	"\xE2\x89"c[],		// too short
+	"\xC0\x8A",
+	"\xE0\x80\x8A",
+	"\xF0\x80\x80\x8A",
+	"\xF8\x80\x80\x80\x8A",
+	"\xFC\x80\x80\x80\x80\x8A",
+    ];
+
+    for (int j = 0; j < s4.length; j++)
+    {
+	try
+	{
+	    i = 0;
+	    c = decode(s4[j], i);
+	    assert(0);
+	}
+	catch (Object o)
+	{
+	    i = 23;
+	}
+	assert(i == 23);
+    }
+}
+
+/** ditto */
+
+dchar decode(in wchar[] s, inout size_t idx)
+    in
+    {
+	assert(idx >= 0 && idx < s.length);
+    }
+    out (result)
+    {
+	assert(isValidDchar(result));
+    }
+    body
+    {
+	string msg;
+	dchar V;
+	size_t i = idx;
+	uint u = s[i];
+
+	if (u & ~0x7F)
+	{   if (u >= 0xD800 && u <= 0xDBFF)
+	    {   uint u2;
+
+		if (i + 1 == s.length)
+		{   msg = "surrogate UTF-16 high value past end of string";
+		    goto Lerr;
+		}
+		u2 = s[i + 1];
+		if (u2 < 0xDC00 || u2 > 0xDFFF)
+		{   msg = "surrogate UTF-16 low value out of range";
+		    goto Lerr;
+		}
+		u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00);
+		i += 2;
+	    }
+	    else if (u >= 0xDC00 && u <= 0xDFFF)
+	    {   msg = "unpaired surrogate UTF-16 value";
+		goto Lerr;
+	    }
+	    else if (u == 0xFFFE || u == 0xFFFF)
+	    {   msg = "illegal UTF-16 value";
+		goto Lerr;
+	    }
+	    else
+		i++;
+	}
+	else
+	{
+	    i++;
+	}
+
+	idx = i;
+	return cast(dchar)u;
+
+      Lerr:
+	  onUnicodeError(msg, i);
+	return cast(dchar)u; // dummy return
+    }
+
+/** ditto */
+
+dchar decode(in dchar[] s, inout size_t idx)
+    in
+    {
+	assert(idx >= 0 && idx < s.length);
+    }
+    body
+    {
+	size_t i = idx;
+	dchar c = s[i];
+
+	if (!isValidDchar(c))
+	    goto Lerr;
+	idx = i + 1;
+	return c;
+
+      Lerr:
+	  onUnicodeError("invalid UTF-32 value", i);
+	return c; // dummy return
+    }
+
+
+/* =================== Encode ======================= */
+
+/*******************************
+ * Encodes character c and appends it to array s[].
+ */
+void encode(inout char[] s, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	char[] r = s;
+
+	if (c <= 0x7F)
+	{
+	    r ~= cast(char) c;
+	}
+	else
+	{
+	    char[4] buf;
+	    uint L;
+
+	    if (c <= 0x7FF)
+	    {
+		buf[0] = cast(char)(0xC0 | (c >> 6));
+		buf[1] = cast(char)(0x80 | (c & 0x3F));
+		L = 2;
+	    }
+	    else if (c <= 0xFFFF)
+	    {
+		buf[0] = cast(char)(0xE0 | (c >> 12));
+		buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+		buf[2] = cast(char)(0x80 | (c & 0x3F));
+		L = 3;
+	    }
+	    else if (c <= 0x10FFFF)
+	    {
+		buf[0] = cast(char)(0xF0 | (c >> 18));
+		buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
+		buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+		buf[3] = cast(char)(0x80 | (c & 0x3F));
+		L = 4;
+	    }
+	    else
+	    {
+		assert(0);
+	    }
+	    r ~= buf[0 .. L];
+	}
+	s = r;
+    }
+
+unittest
+{
+    debug(utf) printf("utf.encode.unittest\n");
+
+    char[] s = "abcd".dup;
+    encode(s, cast(dchar)'a');
+    assert(s.length == 5);
+    assert(s == "abcda");
+
+    encode(s, cast(dchar)'\u00A9');
+    assert(s.length == 7);
+    assert(s == "abcda\xC2\xA9");
+    //assert(s == "abcda\u00A9");	// BUG: fix compiler
+
+    encode(s, cast(dchar)'\u2260');
+    assert(s.length == 10);
+    assert(s == "abcda\xC2\xA9\xE2\x89\xA0");
+}
+
+/** ditto */
+
+void encode(inout wchar[] s, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	wchar[] r = s;
+
+	if (c <= 0xFFFF)
+	{
+	    r ~= cast(wchar) c;
+	}
+	else
+	{
+	    wchar[2] buf;
+
+	    buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
+	    buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
+	    r ~= buf;
+	}
+	s = r;
+    }
+
+/** ditto */
+void encode(inout dchar[] s, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	s ~= c;
+    }
+
+/**
+Returns the code length of $(D c) in the encoding using $(D C) as a
+code point. The code is returned in character count, not in bytes.
+ */
+
+ubyte codeLength(C)(dchar c)
+{
+
+    static if (C.sizeof == 1)
+    {
+        return
+            c <= 0x7F ? 1
+            : c <= 0x7FF ? 2
+            : c <= 0xFFFF ? 3
+            : c <= 0x10FFFF ? 4
+            : (assert(false), 6);
+}
+
+    else static if (C.sizeof == 2)
+{
+	return c <= 0xFFFF ? 1 : 2;
+    }
+    else
+    {
+        static assert(C.sizeof == 4);
+        return 1;
+    }
+}
+
+/* =================== Validation ======================= */
+
+/***********************************
+Checks to see if string is well formed or not. $(D S) can be an array
+ of $(D char), $(D wchar), or $(D dchar). Throws a $(D UtfException)
+ if it is not. Use to check all untrusted input for correctness.
+ */
+void validate(S)(in S s)
+{
+    auto len = s.length;
+    for (size_t i = 0; i < len; )
+    {
+	decode(s, i);
+    }
+}
+
+/* =================== Conversion to UTF8 ======================= */
+
+char[] toUTF8(char[4] buf, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	if (c <= 0x7F)
+	{
+	    buf[0] = cast(char) c;
+	    return buf[0 .. 1];
+	}
+	else if (c <= 0x7FF)
+	{
+	    buf[0] = cast(char)(0xC0 | (c >> 6));
+	    buf[1] = cast(char)(0x80 | (c & 0x3F));
+	    return buf[0 .. 2];
+	}
+	else if (c <= 0xFFFF)
+	{
+	    buf[0] = cast(char)(0xE0 | (c >> 12));
+	    buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+	    buf[2] = cast(char)(0x80 | (c & 0x3F));
+	    return buf[0 .. 3];
+	}
+	else if (c <= 0x10FFFF)
+	{
+	    buf[0] = cast(char)(0xF0 | (c >> 18));
+	    buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
+	    buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+	    buf[3] = cast(char)(0x80 | (c & 0x3F));
+	    return buf[0 .. 4];
+	}
+	assert(0);
+    }
+
+/*******************
+ * Encodes string s into UTF-8 and returns the encoded string.
+ */
+string toUTF8(string s)
+    in
+    {
+	validate(s);
+    }
+    body
+    {
+	return s;
+    }
+
+/** ditto */
+string toUTF8(in wchar[] s)
+{
+    char[] r;
+    size_t i;
+    size_t slen = s.length;
+
+    r.length = slen;
+
+    for (i = 0; i < slen; i++)
+    {	wchar c = s[i];
+
+	if (c <= 0x7F)
+	    r[i] = cast(char)c;		// fast path for ascii
+	else
+	{
+	    r.length = i;
+	    foreach (dchar c; s[i .. slen])
+	    {
+		encode(r, c);
+	    }
+	    break;
+	}
+    }
+    return cast(string)r;
+}
+
+/** ditto */
+string toUTF8(in dchar[] s)
+{
+    char[] r;
+    size_t i;
+    size_t slen = s.length;
+
+    r.length = slen;
+
+    for (i = 0; i < slen; i++)
+    {	dchar c = s[i];
+
+	if (c <= 0x7F)
+	    r[i] = cast(char)c;		// fast path for ascii
+	else
+	{
+	    r.length = i;
+	    foreach (dchar d; s[i .. slen])
+	    {
+		encode(r, d);
+	    }
+	    break;
+	}
+    }
+    return cast(string)r;
+}
+
+/* =================== Conversion to UTF16 ======================= */
+
+wchar[] toUTF16(wchar[2] buf, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	if (c <= 0xFFFF)
+	{
+	    buf[0] = cast(wchar) c;
+	    return buf[0 .. 1];
+	}
+	else
+	{
+	    buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
+	    buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
+	    return buf[0 .. 2];
+	}
+    }
+
+/****************
+ * Encodes string s into UTF-16 and returns the encoded string.
+ * toUTF16z() is suitable for calling the 'W' functions in the Win32 API that take
+ * an LPWSTR or LPCWSTR argument.
+ */
+wstring toUTF16(in char[] s)
+{
+    wchar[] r;
+    size_t slen = s.length;
+
+    r.length = slen;
+    r.length = 0;
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c <= 0x7F)
+	{
+	    i++;
+	    r ~= cast(wchar)c;
+	}
+	else
+	{
+	    c = decode(s, i);
+	    encode(r, c);
+	}
+    }
+    return cast(wstring)r;
+}
+
+alias const(wchar)* wptr;
+/** ditto */
+wptr toUTF16z(in char[] s)
+{
+    wchar[] r;
+    size_t slen = s.length;
+
+    r.length = slen + 1;
+    r.length = 0;
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c <= 0x7F)
+	{
+	    i++;
+	    r ~= cast(wchar)c;
+	}
+	else
+	{
+	    c = decode(s, i);
+	    encode(r, c);
+	}
+    }
+    r ~= "\000";
+    return r.ptr;
+}
+
+/** ditto */
+wstring toUTF16(wstring s)
+    in
+    {
+	validate(s);
+    }
+    body
+    {
+	return s;
+    }
+
+/** ditto */
+wstring toUTF16(in dchar[] s)
+{
+    wchar[] r;
+    size_t slen = s.length;
+
+    r.length = slen;
+    r.length = 0;
+    for (size_t i = 0; i < slen; i++)
+    {
+	encode(r, s[i]);
+    }
+    return cast(wstring)r;
+}
+
+/* =================== Conversion to UTF32 ======================= */
+
+/*****
+ * Encodes string s into UTF-32 and returns the encoded string.
+ */
+dstring toUTF32(in char[] s)
+{
+    dchar[] r;
+    size_t slen = s.length;
+    size_t j = 0;
+
+    r.length = slen;		// r[] will never be longer than s[]
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c >= 0x80)
+	    c = decode(s, i);
+	else
+	    i++;		// c is ascii, no need for decode
+	r[j++] = c;
+    }
+    return cast(dstring)r[0 .. j];
+}
+
+/** ditto */
+dstring toUTF32(in wchar[] s)
+{
+    dchar[] r;
+    size_t slen = s.length;
+    size_t j = 0;
+
+    r.length = slen;		// r[] will never be longer than s[]
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c >= 0x80)
+	    c = decode(s, i);
+	else
+	    i++;		// c is ascii, no need for decode
+	r[j++] = c;
+    }
+    return cast(dstring)r[0 .. j];
+}
+
+/** ditto */
+dstring toUTF32(dstring s)
+    in
+    {
+	validate(s);
+    }
+    body
+    {
+	return s;
+    }
+
+/* ================================ tests ================================== */
+
+unittest
+{
+    debug(utf) printf("utf.toUTF.unittest\n");
+
+    auto c = "hello"c[];
+    auto w = toUTF16(c);
+    assert(w == "hello");
+    auto d = toUTF32(c);
+    assert(d == "hello");
+
+    c = toUTF8(w);
+    assert(c == "hello");
+    d = toUTF32(w);
+    assert(d == "hello");
+
+    c = toUTF8(d);
+    assert(c == "hello");
+    w = toUTF16(d);
+    assert(w == "hello");
+
+
+    c = "hel\u1234o";
+    w = toUTF16(c);
+    assert(w == "hel\u1234o");
+    d = toUTF32(c);
+    assert(d == "hel\u1234o");
+
+    c = toUTF8(w);
+    assert(c == "hel\u1234o");
+    d = toUTF32(w);
+    assert(d == "hel\u1234o");
+
+    c = toUTF8(d);
+    assert(c == "hel\u1234o");
+    w = toUTF16(d);
+    assert(w == "hel\u1234o");
+
+
+    c = "he\U0010AAAAllo";
+    w = toUTF16(c);
+    //foreach (wchar c; w) printf("c = x%x\n", c);
+    //foreach (wchar c; cast(wstring)"he\U0010AAAAllo") printf("c = x%x\n", c);
+    assert(w == "he\U0010AAAAllo");
+    d = toUTF32(c);
+    assert(d == "he\U0010AAAAllo");
+
+    c = toUTF8(w);
+    assert(c == "he\U0010AAAAllo");
+    d = toUTF32(w);
+    assert(d == "he\U0010AAAAllo");
+
+    c = toUTF8(d);
+    assert(c == "he\U0010AAAAllo");
+    w = toUTF16(d);
+    assert(w == "he\U0010AAAAllo");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/dmd/win32.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,175 @@
+# Makefile to build the D runtime library core components for Posix
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR=..\..\..\lib
+DOCDIR=..\..\..\doc
+IMPDIR=..\..\..\import
+LIBBASENAME=druntime_rt_dmd.lib
+#MODULES=bitop exception memory runtime thread vararg \
+#	$(addprefix sync/,barrier condition config exception mutex rwmutex semaphore)
+BUILDS=debug release unittest
+
+MODULES_BASE= \
+	aaA.d \
+	aApply.d \
+	aApplyR.d \
+	adi.d \
+	arrayassign.d \
+	arraybyte.d \
+	arraycast.d \
+	arraycat.d \
+	arraydouble.d \
+	arrayfloat.d \
+	arrayint.d \
+	arrayreal.d \
+	arrayshort.d \
+	cast_.d \
+	cover.d \
+	dmain2.d \
+	invariant.d \
+	invariant_.d \
+	lifetime.d \
+	memory.d \
+	memset.d \
+	obj.d \
+	object_.d \
+	qsort.d \
+	switch_.d \
+	trace.d
+# NOTE: trace.d and cover.d are not necessary for a successful build
+#       as both are used for debugging features (profiling and coverage)
+# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and
+#       minit.asm is not used by dmd for Linux
+
+MODULES_UTIL= \
+	util\console.d \
+	util\cpuid.d \
+	util\ctype.d \
+	util\string.d \
+	util\utf.d
+
+MODULES_TI= \
+	typeinfo\ti_AC.d \
+	typeinfo\ti_Acdouble.d \
+	typeinfo\ti_Acfloat.d \
+	typeinfo\ti_Acreal.d \
+	typeinfo\ti_Adouble.d \
+	typeinfo\ti_Afloat.d \
+	typeinfo\ti_Ag.d \
+	typeinfo\ti_Aint.d \
+	typeinfo\ti_Along.d \
+	typeinfo\ti_Areal.d \
+	typeinfo\ti_Ashort.d \
+	typeinfo\ti_byte.d \
+	typeinfo\ti_C.d \
+	typeinfo\ti_cdouble.d \
+	typeinfo\ti_cfloat.d \
+	typeinfo\ti_char.d \
+	typeinfo\ti_creal.d \
+	typeinfo\ti_dchar.d \
+	typeinfo\ti_delegate.d \
+	typeinfo\ti_double.d \
+	typeinfo\ti_float.d \
+	typeinfo\ti_idouble.d \
+	typeinfo\ti_ifloat.d \
+	typeinfo\ti_int.d \
+	typeinfo\ti_ireal.d \
+	typeinfo\ti_long.d \
+	typeinfo\ti_ptr.d \
+	typeinfo\ti_real.d \
+	typeinfo\ti_short.d \
+	typeinfo\ti_ubyte.d \
+	typeinfo\ti_uint.d \
+	typeinfo\ti_ulong.d \
+	typeinfo\ti_ushort.d \
+	typeinfo\ti_void.d \
+	typeinfo\ti_wchar.d
+
+C_SRCS=complex.c critical.c deh.c monitor.c
+
+# Symbols
+
+CC=dmc
+DMD=dmd
+DOCFLAGS=-version=DDoc
+DFLAGS_release=-d -release -O -inline -w -nofloat
+DFLAGS_debug=-d -g -w -nofloat
+DFLAGS_unittest=$(DFLAGS_release) -unittest
+CFLAGS_release=-mn -6 -r
+CFLAGS_debug=-g -mn -6 -r
+CFLAGS_unittest=$(CFLAGS_release)
+
+# Derived symbols
+
+C_OBJS=complex.obj critical.obj deh.obj monitor.obj
+AS_OBJS=minit.obj
+ALL_MODULES=$(MODULES_BASE) $(MODULES_UTIL) $(MODULES_TI)
+D_SRCS=$(ALL_MODULES)
+ALLLIBS=\
+	$(LIBDIR)\debug\$(LIBBASENAME) \
+	$(LIBDIR)\release\$(LIBBASENAME) \
+	$(LIBDIR)\unittest\$(LIBBASENAME)
+
+# Patterns
+
+#$(LIBDIR)\%\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS)
+#	$(CC) -c $(CFLAGS_$*) $(C_SRCS)
+#	$(DMD) $(DFLAGS_$*) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS)
+#	del $(C_OBJS)
+
+#$(DOCDIR)\%.html : %.d
+#	$(DMD) -c -d -o- -Df$@ $<
+
+#$(IMPDIR)\%.di : %.d
+#	$(DMD) -c -d -o- -Hf$@ $<
+
+# Patterns - debug
+
+$(LIBDIR)\debug\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS)
+	$(CC) -c $(CFLAGS_debug) $(C_SRCS)
+	$(DMD) $(DFLAGS_debug) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS)
+	del $(C_OBJS)
+
+# Patterns - release
+
+$(LIBDIR)\release\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS)
+	$(CC) -c $(CFLAGS_release) $(C_SRCS)
+	$(DMD) $(DFLAGS_release) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS)
+	del $(C_OBJS)
+
+# Patterns - unittest
+
+$(LIBDIR)\unittest\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS)
+	$(CC) -c $(CFLAGS_unittest) $(C_SRCS)
+	$(DMD) $(DFLAGS_unittest) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS)
+	del $(C_OBJS)
+
+# Patterns - asm
+
+minit.obj : minit.asm
+	$(CC) -c $**
+
+# Rulez
+
+all : $(BUILDS) doc
+
+debug : $(LIBDIR)\debug\$(LIBBASENAME) $(IMPORTS)
+release : $(LIBDIR)\release\$(LIBBASENAME) $(IMPORTS)
+unittest : $(LIBDIR)\unittest\$(LIBBASENAME) $(IMPORTS)
+#doc : $(DOCS)
+
+clean :
+	del $(IMPORTS) $(DOCS) $(ALLLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/aApply.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,386 @@
+/**
+ * This code handles decoding UTF strings for foreach loops.  There are 6
+ * combinations of conversions between char, wchar, and dchar, and 2 of each
+ * of those.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.aApply;
+
+private import rt.util.utf;
+
+/**********************************************
+ */
+
+// dg is D, but _aApplycd() is C
+extern (D) typedef int delegate(void *) dg_t;
+
+extern (C) int _aApplycd1(char[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycd1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+
+        d = aa[i];
+        if (d & 0x80)
+            d = decode(aa, i);
+        else
+            i++;
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywd1(wchar[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywd1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+
+        d = aa[i];
+        if (d & ~0x7F)
+            d = decode(aa, i);
+        else
+            i++;
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplycw1(char[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycw1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+        wchar w;
+
+        w = aa[i];
+        if (w & 0x80)
+        {   d = decode(aa, i);
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+                w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(cast(void *)&w);
+                if (result)
+                    break;
+                w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        else
+            i++;
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywc1(wchar[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywc1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+        wchar w;
+        char c;
+
+        w = aa[i];
+        if (w & ~0x7F)
+        {
+            char[4] buf;
+
+            d = decode(aa, i);
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)w;
+            i++;
+        }
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydc1(dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
+    foreach (dchar d; aa)
+    {
+        char c;
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {
+            c = cast(char)d;
+        }
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydw1(dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
+    foreach (dchar d; aa)
+    {
+        wchar w;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+            w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(cast(void *)&w);
+            if (result)
+                break;
+            w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+
+/****************************************************************************/
+
+// dg is D, but _aApplycd2() is C
+extern (D) typedef int delegate(void *, void *) dg2_t;
+
+extern (C) int _aApplycd2(char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycd2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+
+        d = aa[i];
+        if (d & 0x80)
+        {
+            n = i;
+            d = decode(aa, n);
+            n -= i;
+        }
+        else
+            n = 1;
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywd2(wchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywd2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+
+        d = aa[i];
+        if (d & ~0x7F)
+        {
+            n = i;
+            d = decode(aa, n);
+            n -= i;
+        }
+        else
+            n = 1;
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplycw2(char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycw2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+        wchar w;
+
+        w = aa[i];
+        if (w & 0x80)
+        {   n = i;
+            d = decode(aa, n);
+            n -= i;
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+                w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(&i, cast(void *)&w);
+                if (result)
+                    break;
+                w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        else
+            n = 1;
+        result = dg(&i, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywc2(wchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywc2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+        wchar w;
+        char c;
+
+        w = aa[i];
+        if (w & ~0x7F)
+        {
+            char[4] buf;
+
+            n = i;
+            d = decode(aa, n);
+            n -= i;
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)w;
+            n = 1;
+        }
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydc2(dchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplydc2(), len = %d\n", len);
+    for (i = 0; i < len; i++)
+    {   dchar d;
+        char c;
+
+        d = aa[i];
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)d;
+        }
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydw2(dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
+    foreach (size_t i, dchar d; aa)
+    {
+        wchar w;
+        auto j = i;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+            w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(&j, cast(void *)&w);
+            if (result)
+                break;
+            w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(&j, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/aApplyR.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,957 @@
+/**
+ * This code handles decoding UTF strings for foreach_reverse loops.  There are
+ * 6 combinations of conversions between char, wchar, and dchar, and 2 of each
+ * of those.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.aApplyR;
+
+/* This code handles decoding UTF strings for foreach_reverse loops.
+ * There are 6 combinations of conversions between char, wchar,
+ * and dchar, and 2 of each of those.
+ */
+
+private import rt.util.utf;
+
+/**********************************************/
+/* 1 argument versions */
+
+// dg is D, but _aApplyRcd() is C
+extern (D) typedef int delegate(void *) dg_t;
+
+extern (C) int _aApplyRcd1(in char[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d & 0x80)
+        {   char c = cast(char)d;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+        }
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcd1.unittest\n");
+
+    auto s = "hello"c[];
+    int i;
+
+    foreach_reverse(dchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(dchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == '\U00100456'); break;
+            case 2:     assert(d == '\u1234'); break;
+            case 3:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwd1(in wchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwd1.unittest\n");
+
+    auto s = "hello"w[];
+    int i;
+
+    foreach_reverse(dchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(dchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == '\U00100456'); break;
+            case 2:     assert(d == '\u1234'); break;
+            case 3:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRcw1(in char[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        wchar w;
+
+        i--;
+        w = aa[i];
+        if (w & 0x80)
+        {   char c = cast(char)w;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+                w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(cast(void *)&w);
+                if (result)
+                    break;
+                w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcw1.unittest\n");
+
+    auto s = "hello"c[];
+    int i;
+
+    foreach_reverse(wchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(wchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xDBC1); break;
+            case 2:     assert(d == 0xDC56); break;
+            case 3:     assert(d == 0x1234); break;
+            case 4:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwc1(in wchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        char c;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        c = cast(char)d;
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwc1.unittest\n");
+
+    auto s = "hello"w[];
+    int i;
+
+    foreach_reverse(char d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(char d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xF4); break;
+            case 2:     assert(d == 0x80); break;
+            case 3:     assert(d == 0x91); break;
+            case 4:     assert(d == 0x96); break;
+            case 5:     assert(d == 0xE1); break;
+            case 6:     assert(d == 0x88); break;
+            case 7:     assert(d == 0xB4); break;
+            case 8:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdc1(in dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0;)
+    {   dchar d = aa[--i];
+        char c;
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {
+            c = cast(char)d;
+        }
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdc1.unittest\n");
+
+    auto s = "hello"d[];
+    int i;
+
+    foreach_reverse(char d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(char d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xF4); break;
+            case 2:     assert(d == 0x80); break;
+            case 3:     assert(d == 0x91); break;
+            case 4:     assert(d == 0x96); break;
+            case 5:     assert(d == 0xE1); break;
+            case 6:     assert(d == 0x88); break;
+            case 7:     assert(d == 0xB4); break;
+            case 8:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdw1(in dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d = aa[--i];
+        wchar w;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+            w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(cast(void *)&w);
+            if (result)
+                break;
+            w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdw1.unittest\n");
+
+    auto s = "hello"d[];
+    int i;
+
+    foreach_reverse(wchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(wchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xDBC1); break;
+            case 2:     assert(d == 0xDC56); break;
+            case 3:     assert(d == 0x1234); break;
+            case 4:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
+
+
+/****************************************************************************/
+/* 2 argument versions */
+
+// dg is D, but _aApplyRcd2() is C
+extern (D) typedef int delegate(void *, void *) dg2_t;
+
+extern (C) int _aApplyRcd2(in char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplyRcd2(), len = %d\n", len);
+    for (i = len; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d & 0x80)
+        {   char c = cast(char)d;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+        }
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcd2.unittest\n");
+
+    auto s = "hello"c[];
+    int i;
+
+    foreach_reverse(k, dchar d; s)
+    {
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, dchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); assert(k == 8); break;
+            case 1:     assert(d == '\U00100456'); assert(k == 4); break;
+            case 2:     assert(d == '\u1234'); assert(k == 1); break;
+            case 3:     assert(d == 'a'); assert(k == 0); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwd2(in wchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwd2.unittest\n");
+
+    auto s = "hello"w[];
+    int i;
+
+    foreach_reverse(k, dchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, dchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 4); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == '\U00100456'); break;
+            case 2:     assert(k == 1); assert(d == '\u1234'); break;
+            case 3:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRcw2(in char[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        wchar w;
+
+        i--;
+        w = aa[i];
+        if (w & 0x80)
+        {   char c = cast(char)w;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+                w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(&i, cast(void *)&w);
+                if (result)
+                    break;
+                w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        result = dg(&i, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcw2.unittest\n");
+
+    auto s = "hello"c[];
+    int i;
+
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 8); assert(d == 'b'); break;
+            case 1:     assert(k == 4); assert(d == 0xDBC1); break;
+            case 2:     assert(k == 4); assert(d == 0xDC56); break;
+            case 3:     assert(k == 1); assert(d == 0x1234); break;
+            case 4:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwc2(in wchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        char c;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        c = cast(char)d;
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwc2.unittest\n");
+
+    auto s = "hello"w[];
+    int i;
+
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 4); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == 0xF4); break;
+            case 2:     assert(k == 2); assert(d == 0x80); break;
+            case 3:     assert(k == 2); assert(d == 0x91); break;
+            case 4:     assert(k == 2); assert(d == 0x96); break;
+            case 5:     assert(k == 1); assert(d == 0xE1); break;
+            case 6:     assert(k == 1); assert(d == 0x88); break;
+            case 7:     assert(k == 1); assert(d == 0xB4); break;
+            case 8:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdc2(in dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d = aa[--i];
+        char c;
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)d;
+        }
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdc2.unittest\n");
+
+    auto s = "hello"d[];
+    int i;
+
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 3); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == 0xF4); break;
+            case 2:     assert(k == 2); assert(d == 0x80); break;
+            case 3:     assert(k == 2); assert(d == 0x91); break;
+            case 4:     assert(k == 2); assert(d == 0x96); break;
+            case 5:     assert(k == 1); assert(d == 0xE1); break;
+            case 6:     assert(k == 1); assert(d == 0x88); break;
+            case 7:     assert(k == 1); assert(d == 0xB4); break;
+            case 8:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdw2(in dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d = aa[--i];
+        wchar w;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+            w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(&i, cast(void *)&w);
+            if (result)
+                break;
+            w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(&i, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdw2.unittest\n");
+
+    auto s = "hello"d[];
+    int i;
+
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 3); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == 0xDBC1); break;
+            case 2:     assert(k == 2); assert(d == 0xDC56); break;
+            case 3:     assert(k == 1); assert(d == 0x1234); break;
+            case 4:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/aaA.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,872 @@
+/**
+ * Implementation of associative arrays.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.aaA;
+
+private
+{
+    import core.stdc.stdarg;
+    import core.stdc.string;
+    import core.stdc.stdio;
+
+    enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001,
+        NO_SCAN  = 0b0000_0010,
+        NO_MOVE  = 0b0000_0100,
+        ALL_BITS = 0b1111_1111
+    }
+
+    extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
+    extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
+    extern (C) void  gc_free( void* p );
+}
+
+// Auto-rehash and pre-allocate - Dave Fladebo
+
+immutable size_t[] prime_list = [
+              97UL,            389UL,
+           1_543UL,          6_151UL,
+          24_593UL,         98_317UL,
+          393_241UL,      1_572_869UL,
+        6_291_469UL,     25_165_843UL,
+      100_663_319UL,    402_653_189UL,
+    1_610_612_741UL,  4_294_967_291UL,
+//  8_589_934_513UL, 17_179_869_143UL
+];
+
+/* This is the type of the return value for dynamic arrays.
+ * It should be a type that is returned in registers.
+ * Although DMD will return types of Array in registers,
+ * gcc will not, so we instead use a 'long'.
+ */
+alias long ArrayRet_t;
+
+struct Array
+{
+    size_t length;
+    void* ptr;
+}
+
+struct aaA
+{
+    aaA *left;
+    aaA *right;
+    hash_t hash;
+    /* key   */
+    /* value */
+}
+
+struct BB
+{
+    aaA*[] b;
+    size_t nodes;       // total number of aaA nodes
+    TypeInfo keyti;     // TODO: replace this with TypeInfo_AssociativeArray when available in _aaGet()
+}
+
+/* This is the type actually seen by the programmer, although
+ * it is completely opaque.
+ */
+
+struct AA
+{
+    BB* a;
+}
+
+/**********************************
+ * Align to next pointer boundary, so that
+ * GC won't be faced with misaligned pointers
+ * in value.
+ */
+
+size_t aligntsize(size_t tsize)
+{
+    // Is pointer alignment on the x64 4 bytes or 8?
+    return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
+}
+
+extern (C):
+
+/*************************************************
+ * Invariant for aa.
+ */
+
+/+
+void _aaInvAh(aaA*[] aa)
+{
+    for (size_t i = 0; i < aa.length; i++)
+    {
+        if (aa[i])
+            _aaInvAh_x(aa[i]);
+    }
+}
+
+private int _aaCmpAh_x(aaA *e1, aaA *e2)
+{   int c;
+
+    c = e1.hash - e2.hash;
+    if (c == 0)
+    {
+        c = e1.key.length - e2.key.length;
+        if (c == 0)
+            c = memcmp((char *)e1.key, (char *)e2.key, e1.key.length);
+    }
+    return c;
+}
+
+private void _aaInvAh_x(aaA *e)
+{
+    hash_t key_hash;
+    aaA *e1;
+    aaA *e2;
+
+    key_hash = getHash(e.key);
+    assert(key_hash == e.hash);
+
+    while (1)
+    {   int c;
+
+        e1 = e.left;
+        if (e1)
+        {
+            _aaInvAh_x(e1);             // ordinary recursion
+            do
+            {
+                c = _aaCmpAh_x(e1, e);
+                assert(c < 0);
+                e1 = e1.right;
+            } while (e1 != null);
+        }
+
+        e2 = e.right;
+        if (e2)
+        {
+            do
+            {
+                c = _aaCmpAh_x(e, e2);
+                assert(c < 0);
+                e2 = e2.left;
+            } while (e2 != null);
+            e = e.right;                // tail recursion
+        }
+        else
+            break;
+    }
+}
++/
+
+/****************************************************
+ * Determine number of entries in associative array.
+ */
+
+size_t _aaLen(AA aa)
+in
+{
+    //printf("_aaLen()+\n");
+    //_aaInv(aa);
+}
+out (result)
+{
+    size_t len = 0;
+
+    void _aaLen_x(aaA* ex)
+    {
+        auto e = ex;
+        len++;
+
+        while (1)
+        {
+            if (e.right)
+               _aaLen_x(e.right);
+            e = e.left;
+            if (!e)
+                break;
+            len++;
+        }
+    }
+
+    if (aa.a)
+    {
+        foreach (e; aa.a.b)
+        {
+            if (e)
+                _aaLen_x(e);
+        }
+    }
+    assert(len == result);
+
+    //printf("_aaLen()-\n");
+}
+body
+{
+    return aa.a ? aa.a.nodes : 0;
+}
+
+
+/*************************************************
+ * Get pointer to value in associative array indexed by key.
+ * Add entry for key if it is not already there.
+ */
+
+void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...)
+in
+{
+    assert(aa);
+}
+out (result)
+{
+    assert(result);
+    assert(aa.a);
+    assert(aa.a.b.length);
+    //assert(_aaInAh(*aa.a, key));
+}
+body
+{
+    auto pkey = cast(void *)(&valuesize + 1);
+    size_t i;
+    aaA *e;
+//printf("keyti = %p\n", keyti);
+//printf("aa = %p\n", aa);
+    auto keysize = aligntsize(keyti.tsize());
+
+    if (!aa.a)
+        aa.a = new BB();
+//printf("aa = %p\n", aa);
+//printf("aa.a = %p\n", aa.a);
+    aa.a.keyti = keyti;
+
+    if (!aa.a.b.length)
+    {
+        alias aaA *pa;
+        auto len = prime_list[0];
+
+        aa.a.b = new pa[len];
+    }
+
+    auto key_hash = keyti.getHash(pkey);
+    //printf("hash = %d\n", key_hash);
+    i = key_hash % aa.a.b.length;
+    auto pe = &aa.a.b[i];
+    while ((e = *pe) !is null)
+    {
+        if (key_hash == e.hash)
+        {
+            auto c = keyti.compare(pkey, e + 1);
+            if (c == 0)
+                goto Lret;
+            pe = (c < 0) ? &e.left : &e.right;
+        }
+        else
+            pe = (key_hash < e.hash) ? &e.left : &e.right;
+    }
+
+    // Not found, create new elem
+    //printf("create new one\n");
+    size_t size = aaA.sizeof + keysize + valuesize;
+    e = cast(aaA *) gc_calloc(size);
+    memcpy(e + 1, pkey, keysize);
+    e.hash = key_hash;
+    *pe = e;
+
+    auto nodes = ++aa.a.nodes;
+    //printf("length = %d, nodes = %d\n", aa.a.b.length, nodes);
+    if (nodes > aa.a.b.length * 4)
+    {
+	//printf("rehash\n");
+        _aaRehash(aa,keyti);
+    }
+
+Lret:
+    return cast(void *)(e + 1) + keysize;
+}
+
+
+/*************************************************
+ * Get pointer to value in associative array indexed by key.
+ * Returns null if it is not already there.
+ */
+
+void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...)
+{
+    //printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
+    if (!aa.a)
+        return null;
+
+    auto pkey = cast(void *)(&valuesize + 1);
+    auto keysize = aligntsize(keyti.tsize());
+    auto len = aa.a.b.length;
+
+    if (len)
+    {
+        auto key_hash = keyti.getHash(pkey);
+        //printf("hash = %d\n", key_hash);
+        size_t i = key_hash % len;
+        auto e = aa.a.b[i];
+        while (e !is null)
+        {
+            if (key_hash == e.hash)
+            {
+                auto c = keyti.compare(pkey, e + 1);
+            if (c == 0)
+                return cast(void *)(e + 1) + keysize;
+                e = (c < 0) ? e.left : e.right;
+            }
+            else
+                e = (key_hash < e.hash) ? e.left : e.right;
+        }
+    }
+    return null;    // not found, caller will throw exception
+}
+
+
+/*************************************************
+ * Determine if key is in aa.
+ * Returns:
+ *      null    not in aa
+ *      !=null  in aa, return pointer to value
+ */
+
+void* _aaIn(AA aa, TypeInfo keyti, ...)
+in
+{
+}
+out (result)
+{
+    //assert(result == 0 || result == 1);
+}
+body
+{
+    if (aa.a)
+    {
+        auto pkey = cast(void *)(&keyti + 1);
+
+        //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.a.length, cast(uint)aa.a.ptr);
+        auto len = aa.a.b.length;
+
+        if (len)
+        {
+            auto key_hash = keyti.getHash(pkey);
+            //printf("hash = %d\n", key_hash);
+            size_t i = key_hash % len;
+            auto e = aa.a.b[i];
+            while (e !is null)
+            {
+                if (key_hash == e.hash)
+                {
+                    auto c = keyti.compare(pkey, e + 1);
+                    if (c == 0)
+                        return cast(void *)(e + 1) + aligntsize(keyti.tsize());
+                    e = (c < 0) ? e.left : e.right;
+                }
+                else
+                    e = (key_hash < e.hash) ? e.left : e.right;
+            }
+        }
+    }
+
+    // Not found
+    return null;
+}
+
+/*************************************************
+ * Delete key entry in aa[].
+ * If key is not in aa[], do nothing.
+ */
+
+void _aaDel(AA aa, TypeInfo keyti, ...)
+{
+    auto pkey = cast(void *)(&keyti + 1);
+    aaA *e;
+
+    if (aa.a && aa.a.b.length)
+    {
+        auto key_hash = keyti.getHash(pkey);
+        //printf("hash = %d\n", key_hash);
+        size_t i = key_hash % aa.a.b.length;
+        auto pe = &aa.a.b[i];
+        while ((e = *pe) !is null) // null means not found
+        {
+            if (key_hash == e.hash)
+            {
+                auto c = keyti.compare(pkey, e + 1);
+                if (c == 0)
+                {
+                    if (!e.left && !e.right)
+                    {
+                        *pe = null;
+                    }
+                    else if (e.left && !e.right)
+                    {
+                        *pe = e.left;
+                         e.left = null;
+                    }
+                    else if (!e.left && e.right)
+                    {
+                        *pe = e.right;
+                         e.right = null;
+                    }
+                    else
+                    {
+                        *pe = e.left;
+                        e.left = null;
+                        do
+                            pe = &(*pe).right;
+                        while (*pe);
+                        *pe = e.right;
+                        e.right = null;
+                    }
+
+                    aa.a.nodes--;
+                    gc_free(e);
+                    break;
+                }
+                pe = (c < 0) ? &e.left : &e.right;
+            }
+            else
+                pe = (key_hash < e.hash) ? &e.left : &e.right;
+        }
+    }
+}
+
+
+/********************************************
+ * Produce array of values from aa.
+ */
+
+ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize)
+in
+{
+    assert(keysize == aligntsize(keysize));
+}
+body
+{
+    size_t resi;
+    Array a;
+
+    void _aaValues_x(aaA* e)
+    {
+        do
+        {
+            memcpy(a.ptr + resi * valuesize,
+                   cast(byte*)e + aaA.sizeof + keysize,
+                   valuesize);
+            resi++;
+            if (e.left)
+            {   if (!e.right)
+                {   e = e.left;
+                    continue;
+                }
+                _aaValues_x(e.left);
+            }
+            e = e.right;
+        } while (e !is null);
+    }
+
+    if (aa.a)
+    {
+        a.length = _aaLen(aa);
+        a.ptr = cast(byte*) gc_malloc(a.length * valuesize,
+                                      valuesize < (void*).sizeof ? BlkAttr.NO_SCAN : 0);
+        resi = 0;
+        foreach (e; aa.a.b)
+        {
+            if (e)
+                _aaValues_x(e);
+        }
+        assert(resi == a.length);
+    }
+    return *cast(ArrayRet_t*)(&a);
+}
+
+
+/********************************************
+ * Rehash an array.
+ */
+
+void* _aaRehash(AA* paa, TypeInfo keyti)
+in
+{
+    //_aaInvAh(paa);
+}
+out (result)
+{
+    //_aaInvAh(result);
+}
+body
+{
+    BB newb;
+
+    void _aaRehash_x(aaA* olde)
+    {
+        while (1)
+        {
+            auto left = olde.left;
+            auto right = olde.right;
+            olde.left = null;
+            olde.right = null;
+
+            aaA *e;
+
+            //printf("rehash %p\n", olde);
+            auto key_hash = olde.hash;
+            size_t i = key_hash % newb.b.length;
+            auto pe = &newb.b[i];
+            while ((e = *pe) !is null)
+            {
+                //printf("\te = %p, e.left = %p, e.right = %p\n", e, e.left, e.right);
+                assert(e.left != e);
+                assert(e.right != e);
+                if (key_hash == e.hash)
+                {
+                    auto c = keyti.compare(olde + 1, e + 1);
+                    assert(c != 0);
+                    pe = (c < 0) ? &e.left : &e.right;
+                }
+                else
+                    pe = (key_hash < e.hash) ? &e.left : &e.right;
+            }
+            *pe = olde;
+
+            if (right)
+            {
+                if (!left)
+                {   olde = right;
+                    continue;
+                }
+                _aaRehash_x(right);
+            }
+            if (!left)
+                break;
+            olde = left;
+        }
+    }
+
+    //printf("Rehash\n");
+    if (paa.a)
+    {
+        auto aa = paa.a;
+        auto len = _aaLen(*paa);
+        if (len)
+        {   size_t i;
+
+            for (i = 0; i < prime_list.length - 1; i++)
+            {
+                if (len <= prime_list[i])
+                    break;
+            }
+            len = prime_list[i];
+            newb.b = new aaA*[len];
+
+            foreach (e; aa.b)
+            {
+                if (e)
+                    _aaRehash_x(e);
+            }
+            delete aa.b;
+
+            newb.nodes = aa.nodes;
+            newb.keyti = aa.keyti;
+        }
+
+        *paa.a = newb;
+        _aaBalance(paa);
+    }
+    return (*paa).a;
+}
+
+/********************************************
+ * Balance an array.
+ */
+
+void _aaBalance(AA* paa)
+{
+    //printf("_aaBalance()\n");
+    if (paa.a)
+    {
+        aaA*[16] tmp;
+        aaA*[] array = tmp;
+        auto aa = paa.a;
+        foreach (j, e; aa.b)
+        {
+            /* Temporarily store contents of bucket in array[]
+             */
+            size_t k = 0;
+            void addToArray(aaA* e)
+            {
+                while (e)
+                {   addToArray(e.left);
+                    if (k == array.length)
+                        array.length = array.length * 2;
+                    array[k++] = e;
+                    e = e.right;
+                }
+            }
+            addToArray(e);
+            /* The contents of the bucket are now sorted into array[].
+             * Rebuild the tree.
+             */
+            void buildTree(aaA** p, size_t x1, size_t x2)
+            {
+                if (x1 >= x2)
+                    *p = null;
+                else
+                {   auto mid = (x1 + x2) >> 1;
+                    *p = array[mid];
+                    buildTree(&(*p).left, x1, mid);
+                    buildTree(&(*p).right, mid + 1, x2);
+                }
+            }
+            auto p = &aa.b[j];
+            buildTree(p, 0, k);
+        }
+    }
+}
+/********************************************
+ * Produce array of N byte keys from aa.
+ */
+
+ArrayRet_t _aaKeys(AA aa, size_t keysize)
+{
+    byte[] res;
+    size_t resi;
+
+    void _aaKeys_x(aaA* e)
+    {
+        do
+        {
+            memcpy(&res[resi * keysize], cast(byte*)(e + 1), keysize);
+            resi++;
+            if (e.left)
+            {   if (!e.right)
+                {   e = e.left;
+                    continue;
+                }
+                _aaKeys_x(e.left);
+            }
+            e = e.right;
+        } while (e !is null);
+    }
+
+    auto len = _aaLen(aa);
+    if (!len)
+        return 0;
+    res = (cast(byte*) gc_malloc(len * keysize,
+                                 !(aa.a.keyti.flags() & 1) ? BlkAttr.NO_SCAN : 0))[0 .. len * keysize];
+    resi = 0;
+    foreach (e; aa.a.b)
+    {
+        if (e)
+            _aaKeys_x(e);
+    }
+    assert(resi == len);
+
+    Array a;
+    a.length = len;
+    a.ptr = res.ptr;
+    return *cast(ArrayRet_t*)(&a);
+}
+
+
+/**********************************************
+ * 'apply' for associative arrays - to support foreach
+ */
+
+// dg is D, but _aaApply() is C
+extern (D) typedef int delegate(void *) dg_t;
+
+int _aaApply(AA aa, size_t keysize, dg_t dg)
+in
+{
+    assert(aligntsize(keysize) == keysize);
+}
+body
+{   int result;
+
+    //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);
+
+    int treewalker(aaA* e)
+    {   int result;
+
+        do
+        {
+            //printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
+            result = dg(cast(void *)(e + 1) + keysize);
+            if (result)
+                break;
+            if (e.right)
+            {   if (!e.left)
+                {
+                    e = e.right;
+                    continue;
+                }
+                result = treewalker(e.right);
+                if (result)
+                    break;
+            }
+            e = e.left;
+        } while (e);
+
+        return result;
+    }
+
+    if (aa.a)
+    {
+        foreach (e; aa.a.b)
+        {
+            if (e)
+            {
+                result = treewalker(e);
+                if (result)
+                    break;
+            }
+        }
+    }
+    return result;
+}
+
+// dg is D, but _aaApply2() is C
+extern (D) typedef int delegate(void *, void *) dg2_t;
+
+int _aaApply2(AA aa, size_t keysize, dg2_t dg)
+in
+{
+    assert(aligntsize(keysize) == keysize);
+}
+body
+{   int result;
+
+    //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);
+
+    int treewalker(aaA* e)
+    {   int result;
+
+        do
+        {
+            //printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
+            result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize);
+            if (result)
+                break;
+            if (e.right)
+            {   if (!e.left)
+                {
+                    e = e.right;
+                    continue;
+                }
+                result = treewalker(e.right);
+                if (result)
+                    break;
+            }
+            e = e.left;
+        } while (e);
+
+        return result;
+    }
+
+    if (aa.a)
+    {
+        foreach (e; aa.a.b)
+        {
+            if (e)
+            {
+                result = treewalker(e);
+                if (result)
+                    break;
+            }
+        }
+    }
+    return result;
+}
+
+
+/***********************************
+ * Construct an associative array of type ti from
+ * length pairs of key/value pairs.
+ */
+
+extern (C)
+BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...)
+{
+    auto valuesize = ti.next.tsize();           // value size
+    auto keyti = ti.key;
+    auto keysize = keyti.tsize();               // key size
+    BB* result;
+
+    //printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length);
+    //printf("tivalue = %.*s\n", ti.next.classinfo.name);
+    if (length == 0 || valuesize == 0 || keysize == 0)
+    {
+        ;
+    }
+    else
+    {
+        va_list q;
+        va_start!(size_t)(q, length);
+
+        result = new BB();
+        result.keyti = keyti;
+        size_t i;
+
+        for (i = 0; i < prime_list.length - 1; i++)
+        {
+            if (length <= prime_list[i])
+                break;
+        }
+        auto len = prime_list[i];
+        result.b = new aaA*[len];
+
+        size_t keystacksize   = (keysize   + int.sizeof - 1) & ~(int.sizeof - 1);
+        size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1);
+
+        size_t keytsize = aligntsize(keysize);
+
+        for (size_t j = 0; j < length; j++)
+        {   void* pkey = q;
+            q += keystacksize;
+            void* pvalue = q;
+            q += valuestacksize;
+            aaA* e;
+
+            auto key_hash = keyti.getHash(pkey);
+            //printf("hash = %d\n", key_hash);
+            i = key_hash % len;
+            auto pe = &result.b[i];
+            while (1)
+            {
+                e = *pe;
+                if (!e)
+                {
+                    // Not found, create new elem
+                    //printf("create new one\n");
+                    e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize];
+                    memcpy(e + 1, pkey, keysize);
+                    e.hash = key_hash;
+                    *pe = e;
+                    result.nodes++;
+                    break;
+                }
+                if (key_hash == e.hash)
+                {
+                    auto c = keyti.compare(pkey, e + 1);
+                    if (c == 0)
+                        break;
+                    pe = (c < 0) ? &e.left : &e.right;
+                }
+                else
+                    pe = (key_hash < e.hash) ? &e.left : &e.right;
+            }
+            memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize);
+        }
+
+        va_end(q);
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/adi.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,603 @@
+/**
+ * Implementation of dynamic array property support routines.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.adi;
+
+//debug=adi;            // uncomment to turn on debugging printf's
+
+private
+{
+    debug(adi) import core.stdc.stdio;
+    import core.stdc.string;
+    import core.stdc.stdlib;
+    import rt.util.utf;
+
+    enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001,
+        NO_SCAN  = 0b0000_0010,
+        NO_MOVE  = 0b0000_0100,
+        ALL_BITS = 0b1111_1111
+    }
+
+    extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
+    extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
+    extern (C) void  gc_free( void* p );
+}
+
+
+struct Array
+{
+    size_t  length;
+    void*   ptr;
+}
+
+/**********************************************
+ * Reverse array of chars.
+ * Handled separately because embedded multibyte encodings should not be
+ * reversed.
+ */
+
+extern (C) long _adReverseChar(char[] a)
+{
+    if (a.length > 1)
+    {
+        char[6] tmp;
+        char[6] tmplo;
+        char* lo = a.ptr;
+        char* hi = &a[length - 1];
+
+        while (lo < hi)
+        {   auto clo = *lo;
+            auto chi = *hi;
+
+            debug(adi) printf("lo = %d, hi = %d\n", lo, hi);
+            if (clo <= 0x7F && chi <= 0x7F)
+            {
+                debug(adi) printf("\tascii\n");
+                *lo = chi;
+                *hi = clo;
+                lo++;
+                hi--;
+                continue;
+            }
+
+            uint stridelo = UTF8stride[clo];
+
+            uint stridehi = 1;
+            while ((chi & 0xC0) == 0x80)
+            {
+                chi = *--hi;
+                stridehi++;
+                assert(hi >= lo);
+            }
+            if (lo == hi)
+                break;
+
+            debug(adi) printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi);
+            if (stridelo == stridehi)
+            {
+
+                memcpy(tmp.ptr, lo, stridelo);
+                memcpy(lo, hi, stridelo);
+                memcpy(hi, tmp.ptr, stridelo);
+                lo += stridelo;
+                hi--;
+                continue;
+            }
+
+            /* Shift the whole array. This is woefully inefficient
+             */
+            memcpy(tmp.ptr, hi, stridehi);
+            memcpy(tmplo.ptr, lo, stridelo);
+            memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo);
+            memcpy(lo, tmp.ptr, stridehi);
+            memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo);
+
+            lo += stridehi;
+            hi = hi - 1 + (stridehi - stridelo);
+        }
+    }
+    return *cast(long*)(&a);
+}
+
+unittest
+{
+    auto a = "abcd"c[];
+
+    auto r = a.dup.reverse;
+    //writefln(r);
+    assert(r == "dcba");
+
+    a = "a\u1235\u1234c";
+    //writefln(a);
+    r = a.dup.reverse;
+    //writefln(r);
+    assert(r == "c\u1234\u1235a");
+
+    a = "ab\u1234c";
+    //writefln(a);
+    r = a.dup.reverse;
+    //writefln(r);
+    assert(r == "c\u1234ba");
+
+    a = "\u3026\u2021\u3061\n";
+    r = a.dup.reverse;
+    assert(r == "\n\u3061\u2021\u3026");
+}
+
+
+/**********************************************
+ * Reverse array of wchars.
+ * Handled separately because embedded multiword encodings should not be
+ * reversed.
+ */
+
+extern (C) long _adReverseWchar(wchar[] a)
+{
+    if (a.length > 1)
+    {
+        wchar[2] tmp;
+        wchar* lo = a.ptr;
+        wchar* hi = &a[length - 1];
+
+        while (lo < hi)
+        {   auto clo = *lo;
+            auto chi = *hi;
+
+            if ((clo < 0xD800 || clo > 0xDFFF) &&
+                (chi < 0xD800 || chi > 0xDFFF))
+            {
+                *lo = chi;
+                *hi = clo;
+                lo++;
+                hi--;
+                continue;
+            }
+
+            int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
+
+            int stridehi = 1;
+            if (chi >= 0xDC00 && chi <= 0xDFFF)
+            {
+                chi = *--hi;
+                stridehi++;
+                assert(hi >= lo);
+            }
+            if (lo == hi)
+                break;
+
+            if (stridelo == stridehi)
+            {   int stmp;
+
+                assert(stridelo == 2);
+                assert(stmp.sizeof == 2 * (*lo).sizeof);
+                stmp = *cast(int*)lo;
+                *cast(int*)lo = *cast(int*)hi;
+                *cast(int*)hi = stmp;
+                lo += stridelo;
+                hi--;
+                continue;
+            }
+
+            /* Shift the whole array. This is woefully inefficient
+             */
+            memcpy(tmp.ptr, hi, stridehi * wchar.sizeof);
+            memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
+            memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
+            memcpy(lo, tmp.ptr, stridehi * wchar.sizeof);
+
+            lo += stridehi;
+            hi = hi - 1 + (stridehi - stridelo);
+        }
+    }
+    return *cast(long*)(&a);
+}
+
+unittest
+{
+    wstring a = "abcd";
+
+    auto r = a.dup.reverse;
+    assert(r == "dcba");
+
+    a = "a\U00012356\U00012346c";
+    r = a.dup.reverse;
+    assert(r == "c\U00012346\U00012356a");
+
+    a = "ab\U00012345c";
+    r = a.dup.reverse;
+    assert(r == "c\U00012345ba");
+}
+
+
+/**********************************************
+ * Support for array.reverse property.
+ */
+
+extern (C) long _adReverse(Array a, size_t szelem)
+out (result)
+{
+    assert(result is *cast(long*)(&a));
+}
+body
+{
+    if (a.length >= 2)
+    {
+        byte*    tmp;
+        byte[16] buffer;
+
+        void* lo = a.ptr;
+        void* hi = a.ptr + (a.length - 1) * szelem;
+
+        tmp = buffer.ptr;
+        if (szelem > 16)
+        {
+            //version (Windows)
+                tmp = cast(byte*) alloca(szelem);
+            //else
+                //tmp = gc_malloc(szelem);
+        }
+
+        for (; lo < hi; lo += szelem, hi -= szelem)
+        {
+            memcpy(tmp, lo,  szelem);
+            memcpy(lo,  hi,  szelem);
+            memcpy(hi,  tmp, szelem);
+        }
+
+        version (Windows)
+        {
+        }
+        else
+        {
+            //if (szelem > 16)
+                // BUG: bad code is generate for delete pointer, tries
+                // to call delclass.
+                //gc_free(tmp);
+        }
+    }
+    return *cast(long*)(&a);
+}
+
+unittest
+{
+    debug(adi) printf("array.reverse.unittest\n");
+
+    int[] a = new int[5];
+    int[] b;
+    size_t i;
+
+    for (i = 0; i < 5; i++)
+        a[i] = i;
+    b = a.reverse;
+    assert(b is a);
+    for (i = 0; i < 5; i++)
+        assert(a[i] == 4 - i);
+
+    struct X20
+    {   // More than 16 bytes in size
+        int a;
+        int b, c, d, e;
+    }
+
+    X20[] c = new X20[5];
+    X20[] d;
+
+    for (i = 0; i < 5; i++)
+    {   c[i].a = i;
+        c[i].e = 10;
+    }
+    d = c.reverse;
+    assert(d is c);
+    for (i = 0; i < 5; i++)
+    {
+        assert(c[i].a == 4 - i);
+        assert(c[i].e == 10);
+    }
+}
+
+/**********************************************
+ * Sort array of chars.
+ */
+
+extern (C) long _adSortChar(char[] a)
+{
+    if (a.length > 1)
+    {
+        dstring da = toUTF32(a);
+        da.sort;
+        size_t i = 0;
+        foreach (dchar d; da)
+        {   char[4] buf;
+            auto t = toUTF8(buf, d);
+            a[i .. i + t.length] = t[];
+            i += t.length;
+        }
+        delete da;
+    }
+    return *cast(long*)(&a);
+}
+
+/**********************************************
+ * Sort array of wchars.
+ */
+
+extern (C) long _adSortWchar(wchar[] a)
+{
+    if (a.length > 1)
+    {
+        dstring da = toUTF32(a);
+        da.sort;
+        size_t i = 0;
+        foreach (dchar d; da)
+        {   wchar[2] buf;
+            auto t = toUTF16(buf, d);
+            a[i .. i + t.length] = t[];
+            i += t.length;
+        }
+        delete da;
+    }
+    return *cast(long*)(&a);
+}
+
+/***************************************
+ * Support for array equality test.
+ * Returns:
+ *      1       equal
+ *      0       not equal
+ */
+
+extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
+{
+    debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
+    if (a1.length != a2.length)
+        return 0; // not equal
+    auto sz = ti.tsize();
+    auto p1 = a1.ptr;
+    auto p2 = a2.ptr;
+
+    if (sz == 1)
+        // We should really have a ti.isPOD() check for this
+        return (memcmp(p1, p2, a1.length) == 0);
+
+    for (size_t i = 0; i < a1.length; i++)
+    {
+        if (!ti.equals(p1 + i * sz, p2 + i * sz))
+            return 0; // not equal
+    }
+    return 1; // equal
+}
+
+extern (C) int _adEq2(Array a1, Array a2, TypeInfo ti)
+{
+    debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
+    if (a1.length != a2.length)
+        return 0;               // not equal
+    if (!ti.equals(&a1, &a2))
+        return 0;
+    return 1;
+}
+unittest
+{
+    debug(adi) printf("array.Eq unittest\n");
+
+    auto a = "hello"c;
+
+    assert(a != "hel");
+    assert(a != "helloo");
+    assert(a != "betty");
+    assert(a == "hello");
+    assert(a != "hxxxx");
+}
+
+/***************************************
+ * Support for array compare test.
+ */
+
+extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti)
+{
+    debug(adi) printf("adCmp()\n");
+    auto len = a1.length;
+    if (a2.length < len)
+        len = a2.length;
+    auto sz = ti.tsize();
+    void *p1 = a1.ptr;
+    void *p2 = a2.ptr;
+
+    if (sz == 1)
+    {   // We should really have a ti.isPOD() check for this
+        auto c = memcmp(p1, p2, len);
+        if (c)
+            return c;
+    }
+    else
+    {
+        for (size_t i = 0; i < len; i++)
+        {
+            auto c = ti.compare(p1 + i * sz, p2 + i * sz);
+            if (c)
+                return c;
+        }
+    }
+    if (a1.length == a2.length)
+        return 0;
+    return (a1.length > a2.length) ? 1 : -1;
+}
+
+extern (C) int _adCmp2(Array a1, Array a2, TypeInfo ti)
+{
+    debug(adi) printf("_adCmp2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
+    return ti.compare(&a1, &a2);
+}
+unittest
+{
+    debug(adi) printf("array.Cmp unittest\n");
+
+    auto a = "hello"c;
+
+    assert(a >  "hel");
+    assert(a >= "hel");
+    assert(a <  "helloo");
+    assert(a <= "helloo");
+    assert(a >  "betty");
+    assert(a >= "betty");
+    assert(a == "hello");
+    assert(a <= "hello");
+    assert(a >= "hello");
+}
+
+/***************************************
+ * Support for array compare test.
+ */
+
+extern (C) int _adCmpChar(Array a1, Array a2)
+{
+  version (X86)
+  {
+    asm
+    {   naked                   ;
+
+        push    EDI             ;
+        push    ESI             ;
+
+        mov    ESI,a1+4[4+ESP]  ;
+        mov    EDI,a2+4[4+ESP]  ;
+
+        mov    ECX,a1[4+ESP]    ;
+        mov    EDX,a2[4+ESP]    ;
+
+        cmp     ECX,EDX         ;
+        jb      GotLength       ;
+
+        mov     ECX,EDX         ;
+
+GotLength:
+        cmp    ECX,4            ;
+        jb    DoBytes           ;
+
+        // Do alignment if neither is dword aligned
+        test    ESI,3           ;
+        jz    Aligned           ;
+
+        test    EDI,3           ;
+        jz    Aligned           ;
+DoAlign:
+        mov    AL,[ESI]         ; //align ESI to dword bounds
+        mov    DL,[EDI]         ;
+
+        cmp    AL,DL            ;
+        jnz    Unequal          ;
+
+        inc    ESI              ;
+        inc    EDI              ;
+
+        test    ESI,3           ;
+
+        lea    ECX,[ECX-1]      ;
+        jnz    DoAlign          ;
+Aligned:
+        mov    EAX,ECX          ;
+
+        // do multiple of 4 bytes at a time
+
+        shr    ECX,2            ;
+        jz    TryOdd            ;
+
+        repe                    ;
+        cmpsd                   ;
+
+        jnz    UnequalQuad      ;
+
+TryOdd:
+        mov    ECX,EAX          ;
+DoBytes:
+        // if still equal and not end of string, do up to 3 bytes slightly
+        // slower.
+
+        and    ECX,3            ;
+        jz    Equal             ;
+
+        repe                    ;
+        cmpsb                   ;
+
+        jnz    Unequal          ;
+Equal:
+        mov    EAX,a1[4+ESP]    ;
+        mov    EDX,a2[4+ESP]    ;
+
+        sub    EAX,EDX          ;
+        pop    ESI              ;
+
+        pop    EDI              ;
+        ret                     ;
+
+UnequalQuad:
+        mov    EDX,[EDI-4]      ;
+        mov    EAX,[ESI-4]      ;
+
+        cmp    AL,DL            ;
+        jnz    Unequal          ;
+
+        cmp    AH,DH            ;
+        jnz    Unequal          ;
+
+        shr    EAX,16           ;
+
+        shr    EDX,16           ;
+
+        cmp    AL,DL            ;
+        jnz    Unequal          ;
+
+        cmp    AH,DH            ;
+Unequal:
+        sbb    EAX,EAX          ;
+        pop    ESI              ;
+
+        or     EAX,1            ;
+        pop    EDI              ;
+
+        ret                     ;
+    }
+  }
+  else
+  {
+    int len;
+    int c;
+
+    debug(adi) printf("adCmpChar()\n");
+    len = a1.length;
+    if (a2.length < len)
+        len = a2.length;
+    c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
+    if (!c)
+        c = cast(int)a1.length - cast(int)a2.length;
+    return c;
+  }
+}
+
+unittest
+{
+    debug(adi) printf("array.CmpChar unittest\n");
+
+    auto a = "hello"c;
+
+    assert(a >  "hel");
+    assert(a >= "hel");
+    assert(a <  "helloo");
+    assert(a <= "helloo");
+    assert(a >  "betty");
+    assert(a >= "betty");
+    assert(a == "hello");
+    assert(a <= "hello");
+    assert(a >= "hello");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/alloca.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,135 @@
+/**
+ * Implementation of alloca() standard C routine.
+ *
+ * Copyright: Copyright Digital Mars 1990 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 1990 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.alloca;
+
+/+
+#if DOS386
+extern size_t _x386_break;
+#else
+extern size_t _pastdata;
+#endif
++/
+
+/*******************************************
+ * Allocate data from the caller's stack frame.
+ * This is a 'magic' function that needs help from the compiler to
+ * work right, do not change its name, do not call it from other compilers.
+ * Input:
+ *      nbytes  number of bytes to allocate
+ *      ECX     address of variable with # of bytes in locals
+ *              This is adjusted upon return to reflect the additional
+ *              size of the stack frame.
+ * Returns:
+ *      EAX     allocated data, null if stack overflows
+ */
+
+extern (C) void* __alloca(int nbytes)
+{
+    asm
+    {
+        naked                   ;
+        mov     EDX,ECX         ;
+        mov     EAX,4[ESP]      ; // get nbytes
+        push    EBX             ;
+        push    EDI             ;
+        push    ESI             ;
+    }
+
+    version (OSX)
+    {
+    asm
+    {
+	add	EAX,15		;
+	and	EAX,0xFFFFFFF0	; // round up to 16 byte boundary
+    }
+    }
+    else
+    {
+    asm
+    {
+	add	EAX,3		;
+	and	EAX,0xFFFFFFFC	; // round up to dword
+    }
+    }
+
+    asm
+    {
+        jnz     Abegin          ;
+        mov     EAX,4           ; // allow zero bytes allocation, 0 rounded to dword is 4..
+    Abegin:
+        mov     ESI,EAX         ; // ESI = nbytes
+        neg     EAX             ;
+        add     EAX,ESP         ; // EAX is now what the new ESP will be.
+        jae     Aoverflow       ;
+    }
+    version (Windows)
+    {
+    asm
+    {
+        // We need to be careful about the guard page
+        // Thus, for every 4k page, touch it to cause the OS to load it in.
+        mov     ECX,EAX         ; // ECX is new location for stack
+        mov     EBX,ESI         ; // EBX is size to "grow" stack
+    L1:
+        test    [ECX+EBX],EBX   ; // bring in page
+        sub     EBX,0x1000      ; // next 4K page down
+        jae     L1              ; // if more pages
+        test    [ECX],EBX       ; // bring in last page
+    }
+    }
+    version (DOS386)
+    {
+    asm
+    {
+        // is ESP off bottom?
+        cmp     EAX,_x386_break ;
+        jbe     Aoverflow       ;
+    }
+    }
+    version (Unix)
+    {
+    asm
+    {
+        cmp     EAX,_pastdata   ;
+        jbe     Aoverflow       ; // Unlikely - ~2 Gbytes under UNIX
+    }
+    }
+    asm
+    {
+        // Copy down to [ESP] the temps on the stack.
+        // The number of temps is (EBP - ESP - locals).
+        mov     ECX,EBP         ;
+        sub     ECX,ESP         ;
+        sub     ECX,[EDX]       ; // ECX = number of temps (bytes) to move.
+        add     [EDX],ESI       ; // adjust locals by nbytes for next call to alloca()
+        mov     ESP,EAX         ; // Set up new stack pointer.
+        add     EAX,ECX         ; // Return value = ESP + temps.
+        mov     EDI,ESP         ; // Destination of copy of temps.
+        add     ESI,ESP         ; // Source of copy.
+        shr     ECX,2           ; // ECX to count of dwords in temps
+                                  // Always at least 4 (nbytes, EIP, ESI,and EDI).
+        rep                     ;
+        movsd                   ;
+        jmp     done            ;
+
+    Aoverflow:
+        // Overflowed the stack.  Return null
+        xor     EAX,EAX         ;
+
+    done:
+        pop     ESI             ;
+        pop     EDI             ;
+        pop     EBX             ;
+        ret                     ;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/arrayassign.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,186 @@
+/**
+ * Implementation of array assignment support routines.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arrayassign;
+
+private
+{
+    import rt.util.string;
+    import core.stdc.string;
+    import core.stdc.stdlib;
+    debug(PRINTF) import core.stdc.stdio;
+}
+
+/**
+ * Does array assignment (not construction) from another
+ * array of the same element type.
+ * ti is the element type.
+ * Handles overlapping copies.
+ */
+extern (C) void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to)
+{
+    debug(PRINTF) printf("_d_arrayassign(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize());
+
+    if (to.length != from.length)
+    {
+        char[10] tmp = void;
+        string msg = "lengths don't match for array copy,"c;
+        msg ~= tmp.intToString(to.length) ~ " = " ~ tmp.intToString(from.length);
+        throw new Exception(msg);
+    }
+
+    auto element_size = ti.tsize();
+
+    /* Need a temporary buffer tmp[] big enough to hold one element
+     */
+    void[16] buf = void;
+    void[] tmp;
+    if (element_size > buf.sizeof)
+        tmp = alloca(element_size)[0 .. element_size];
+    else
+        tmp = buf;
+
+
+    if (to.ptr <= from.ptr)
+    {
+        foreach (i; 0 .. to.length)
+        {
+            void* pto   = to.ptr   + i * element_size;
+            void* pfrom = from.ptr + i * element_size;
+            memcpy(tmp.ptr, pto, element_size);
+            memcpy(pto, pfrom, element_size);
+            ti.postblit(pto);
+            ti.destroy(tmp.ptr);
+        }
+    }
+    else
+    {
+        for (int i = to.length; i--; )
+        {
+            void* pto   = to.ptr   + i * element_size;
+            void* pfrom = from.ptr + i * element_size;
+            memcpy(tmp.ptr, pto, element_size);
+            memcpy(pto, pfrom, element_size);
+            ti.postblit(pto);
+            ti.destroy(tmp.ptr);
+        }
+    }
+    return to;
+}
+
+/**
+ * Does array initialization (not assignment) from another
+ * array of the same element type.
+ * ti is the element type.
+ */
+extern (C) void[] _d_arrayctor(TypeInfo ti, void[] from, void[] to)
+{
+    debug(PRINTF) printf("_d_arrayctor(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize());
+
+    if (to.length != from.length)
+    {
+        char[10] tmp = void;
+        string msg = "lengths don't match for array initialization,"c;
+        msg ~= tmp.intToString(to.length) ~ " = " ~ tmp.intToString(from.length);
+        throw new Exception(msg);
+    }
+
+    auto element_size = ti.tsize();
+
+    int i;
+    try
+    {
+        for (i = 0; i < to.length; i++)
+        {
+            // Copy construction is defined as bit copy followed by postblit.
+            memcpy(to.ptr + i * element_size, from.ptr + i * element_size, element_size);
+            ti.postblit(to.ptr + i * element_size);
+        }
+    }
+    catch (Object o)
+    {
+        /* Destroy, in reverse order, what we've constructed so far
+         */
+        while (i--)
+        {
+            ti.destroy(to.ptr + i * element_size);
+        }
+
+        throw o;
+    }
+    return to;
+}
+
+
+/**
+ * Do assignment to an array.
+ *      p[0 .. count] = value;
+ */
+extern (C) void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti)
+{
+    void* pstart = p;
+
+    auto element_size = ti.tsize();
+
+    //Need a temporary buffer tmp[] big enough to hold one element
+    void[16] buf = void;
+    void[] tmp;
+    if (element_size > buf.sizeof)
+    {
+        tmp = alloca(element_size)[0 .. element_size];
+    }
+    else
+        tmp = buf;
+
+    foreach (i; 0 .. count)
+    {
+        memcpy(tmp.ptr, p, element_size);
+        memcpy(p, value, element_size);
+        ti.postblit(p);
+        ti.destroy(tmp.ptr);
+        p += element_size;
+    }
+    return pstart;
+}
+
+/**
+ * Do construction of an array.
+ *      ti[count] p = value;
+ */
+extern (C) void* _d_arraysetctor(void* p, void* value, int count, TypeInfo ti)
+{
+    void* pstart = p;
+    auto element_size = ti.tsize();
+
+    try
+    {
+        foreach (i; 0 .. count)
+        {
+            // Copy construction is defined as bit copy followed by postblit.
+            memcpy(p, value, element_size);
+            ti.postblit(p);
+            p += element_size;
+        }
+    }
+    catch (Object o)
+    {
+        // Destroy, in reverse order, what we've constructed so far
+        while (p > pstart)
+        {
+            p -= element_size;
+            ti.destroy(p);
+        }
+
+        throw o;
+    }
+    return pstart;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/arraybyte.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,1893 @@
+/**
+ * Contains SSE2 and MMX versions of certain operations for char, byte, and
+ * ubyte ('a', 'g' and 'h' suffixes).
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arraybyte;
+
+import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 4;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.amd3dnow amd3dnow;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+alias byte T;
+
+extern (C):
+
+/* ======================================================================== */
+
+
+/***********************
+ * Computes:
+ *      a[] = b[] + value
+ */
+
+T[] _arraySliceExpAddSliceAssign_a(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_g(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_h(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_g(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_g(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpAddSliceAssign_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1088% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startaddsse2u:
+                    add ESI, 64;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM2, [EAX+32];
+                    movdqu XMM3, [EAX+48];
+                    add EAX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM4;
+                    paddb XMM2, XMM4;
+                    paddb XMM3, XMM4;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startaddsse2a:
+                    add ESI, 64;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM2, [EAX+32];
+                    movdqa XMM3, [EAX+48];
+                    add EAX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM4;
+                    paddb XMM2, XMM4;
+                    paddb XMM3, XMM4;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 1000% faster
+        if (mmx() && a.length >= 32)
+        {
+            auto n = aptr + (a.length & ~31);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 4;
+            startaddmmx:
+                add ESI, 32;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                add EAX, 32;
+                paddb MM0, MM4;
+                paddb MM1, MM4;
+                paddb MM2, MM4;
+                paddb MM3, MM4;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startaddmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        /* trying to be fair and treat normal 32-bit cpu the same way as we do
+         * the SIMD units, with unrolled asm.  There's not enough registers,
+         * really.
+         */
+        else
+        if (a.length >= 4)
+        {
+
+            auto n = aptr + (a.length & ~3);
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov CL, value;
+
+                align 4;
+            startadd386:
+                add ESI, 4;
+                mov DX, [EAX];
+                mov BX, [EAX+2];
+                add EAX, 4;
+                add BL, CL;
+                add BH, CL;
+                add DL, CL;
+                add DH, CL;
+                mov [ESI   -4], DX;
+                mov [ESI+2 -4], BX;
+                cmp ESI, EDI;
+                jb startadd386;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ + value);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpAddSliceAssign_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_a(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_g(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_h(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_g(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_g(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceAddSliceAssign_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 5739% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                version (log) printf("\tsse2 unaligned\n");
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 8;
+                startaddlsse2u:
+                    add ESI, 64;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM2, [EAX+32];
+                    movdqu XMM3, [EAX+48];
+                    add EAX, 64;
+                    movdqu XMM4, [ECX];
+                    movdqu XMM5, [ECX+16];
+                    movdqu XMM6, [ECX+32];
+                    movdqu XMM7, [ECX+48];
+                    add ECX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM5;
+                    paddb XMM2, XMM6;
+                    paddb XMM3, XMM7;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddlsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                version (log) printf("\tsse2 aligned\n");
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 8;
+                startaddlsse2a:
+                    add ESI, 64;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM2, [EAX+32];
+                    movdqa XMM3, [EAX+48];
+                    add EAX, 64;
+                    movdqa XMM4, [ECX];
+                    movdqa XMM5, [ECX+16];
+                    movdqa XMM6, [ECX+32];
+                    movdqa XMM7, [ECX+48];
+                    add ECX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM5;
+                    paddb XMM2, XMM6;
+                    paddb XMM3, XMM7;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddlsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 4428% faster
+        if (mmx() && a.length >= 32)
+        {
+            version (log) printf("\tmmx\n");
+            auto n = aptr + (a.length & ~31);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startaddlmmx:
+                add ESI, 32;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                add EAX, 32;
+                movq MM4, [ECX];
+                movq MM5, [ECX+8];
+                movq MM6, [ECX+16];
+                movq MM7, [ECX+24];
+                add ECX, 32;
+                paddb MM0, MM4;
+                paddb MM1, MM5;
+                paddb MM2, MM6;
+                paddb MM3, MM7;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startaddlmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    version (log) if (aptr < aend) printf("\tbase\n");
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ + *cptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += value
+ */
+
+T[] _arrayExpSliceAddass_a(T[] a, T value)
+{
+    return _arrayExpSliceAddass_g(a, value);
+}
+
+T[] _arrayExpSliceAddass_h(T[] a, T value)
+{
+    return _arrayExpSliceAddass_g(a, value);
+}
+
+T[] _arrayExpSliceAddass_g(T[] a, T value)
+{
+    //printf("_arrayExpSliceAddass_g(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1578% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+            l |= (l << 16);
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startaddasssse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM2, [ESI+32];
+                    movdqu XMM3, [ESI+48];
+                    add ESI, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM4;
+                    paddb XMM2, XMM4;
+                    paddb XMM3, XMM4;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddasssse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startaddasssse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM2, [ESI+32];
+                    movdqa XMM3, [ESI+48];
+                    add ESI, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM4;
+                    paddb XMM2, XMM4;
+                    paddb XMM3, XMM4;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddasssse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 1721% faster
+        if (mmx() && a.length >= 32)
+        {
+
+            auto n = aptr + (a.length & ~31);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 8;
+            startaddassmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                add ESI, 32;
+                paddb MM0, MM4;
+                paddb MM1, MM4;
+                paddb MM2, MM4;
+                paddb MM3, MM4;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startaddassmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceAddass_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += b[]
+ */
+
+T[] _arraySliceSliceAddass_a(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_g(a, b);
+}
+
+T[] _arraySliceSliceAddass_h(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_g(a, b);
+}
+
+T[] _arraySliceSliceAddass_g(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceAddass_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 4727% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 8;
+                startaddasslsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM2, [ESI+32];
+                    movdqu XMM3, [ESI+48];
+                    add ESI, 64;
+                    movdqu XMM4, [ECX];
+                    movdqu XMM5, [ECX+16];
+                    movdqu XMM6, [ECX+32];
+                    movdqu XMM7, [ECX+48];
+                    add ECX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM5;
+                    paddb XMM2, XMM6;
+                    paddb XMM3, XMM7;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddasslsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 8;
+                startaddasslsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM2, [ESI+32];
+                    movdqa XMM3, [ESI+48];
+                    add ESI, 64;
+                    movdqa XMM4, [ECX];
+                    movdqa XMM5, [ECX+16];
+                    movdqa XMM6, [ECX+32];
+                    movdqa XMM7, [ECX+48];
+                    add ECX, 64;
+                    paddb XMM0, XMM4;
+                    paddb XMM1, XMM5;
+                    paddb XMM2, XMM6;
+                    paddb XMM3, XMM7;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddasslsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 3059% faster
+        if (mmx() && a.length >= 32)
+        {
+
+            auto n = aptr + (a.length & ~31);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 8;
+            startaddasslmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                add ESI, 32;
+                movq MM4, [ECX];
+                movq MM5, [ECX+8];
+                movq MM6, [ECX+16];
+                movq MM7, [ECX+24];
+                add ECX, 32;
+                paddb MM0, MM4;
+                paddb MM1, MM5;
+                paddb MM2, MM6;
+                paddb MM3, MM7;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startaddasslmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddass_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+
+/***********************
+ * Computes:
+ *      a[] = b[] - value
+ */
+
+T[] _arraySliceExpMinSliceAssign_a(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_g(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_h(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_g(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_g(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMinSliceAssign_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1189% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubsse2u:
+                    add ESI, 64;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM2, [EAX+32];
+                    movdqu XMM3, [EAX+48];
+                    add EAX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM4;
+                    psubb XMM2, XMM4;
+                    psubb XMM3, XMM4;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubsse2a:
+                    add ESI, 64;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM2, [EAX+32];
+                    movdqa XMM3, [EAX+48];
+                    add EAX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM4;
+                    psubb XMM2, XMM4;
+                    psubb XMM3, XMM4;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 1079% faster
+        if (mmx() && a.length >= 32)
+        {
+            auto n = aptr + (a.length & ~31);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 4;
+            startsubmmx:
+                add ESI, 32;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                add EAX, 32;
+                psubb MM0, MM4;
+                psubb MM1, MM4;
+                psubb MM2, MM4;
+                psubb MM3, MM4;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startsubmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        // trying to be fair and treat normal 32-bit cpu the same way as we do the SIMD units, with unrolled asm.  There's not enough registers, really.
+        else
+        if (a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov CL, value;
+
+                align 4;
+            startsub386:
+                add ESI, 4;
+                mov DX, [EAX];
+                mov BX, [EAX+2];
+                add EAX, 4;
+                sub BL, CL;
+                sub BH, CL;
+                sub DL, CL;
+                sub DH, CL;
+                mov [ESI   -4], DX;
+                mov [ESI+2 -4], BX;
+                cmp ESI, EDI;
+                jb startsub386;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ - value);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMinSliceAssign_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] = b[] - 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(b[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, c[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = value - b[]
+ */
+
+T[] _arrayExpSliceMinSliceAssign_a(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_g(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_h(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_g(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_g(T[] a, T[] b, T value)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arrayExpSliceMinSliceAssign_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 8748% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubrsse2u:
+                    add ESI, 64;
+                    movdqa XMM5, XMM4;
+                    movdqa XMM6, XMM4;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    psubb XMM5, XMM0;
+                    psubb XMM6, XMM1;
+                    movdqu [ESI   -64], XMM5;
+                    movdqu [ESI+16-64], XMM6;
+                    movdqa XMM5, XMM4;
+                    movdqa XMM6, XMM4;
+                    movdqu XMM2, [EAX+32];
+                    movdqu XMM3, [EAX+48];
+                    add EAX, 64;
+                    psubb XMM5, XMM2;
+                    psubb XMM6, XMM3;
+                    movdqu [ESI+32-64], XMM5;
+                    movdqu [ESI+48-64], XMM6;
+                    cmp ESI, EDI;
+                    jb startsubrsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubrsse2a:
+                    add ESI, 64;
+                    movdqa XMM5, XMM4;
+                    movdqa XMM6, XMM4;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    psubb XMM5, XMM0;
+                    psubb XMM6, XMM1;
+                    movdqa [ESI   -64], XMM5;
+                    movdqa [ESI+16-64], XMM6;
+                    movdqa XMM5, XMM4;
+                    movdqa XMM6, XMM4;
+                    movdqa XMM2, [EAX+32];
+                    movdqa XMM3, [EAX+48];
+                    add EAX, 64;
+                    psubb XMM5, XMM2;
+                    psubb XMM6, XMM3;
+                    movdqa [ESI+32-64], XMM5;
+                    movdqa [ESI+48-64], XMM6;
+                    cmp ESI, EDI;
+                    jb startsubrsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 7397% faster
+        if (mmx() && a.length >= 32)
+        {
+            auto n = aptr + (a.length & ~31);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 4;
+            startsubrmmx:
+                add ESI, 32;
+                movq MM5, MM4;
+                movq MM6, MM4;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                psubb MM5, MM0;
+                psubb MM6, MM1;
+                movq [ESI   -32], MM5;
+                movq [ESI+8 -32], MM6;
+                movq MM5, MM4;
+                movq MM6, MM4;
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                add EAX, 32;
+                psubb MM5, MM2;
+                psubb MM6, MM3;
+                movq [ESI+16-32], MM5;
+                movq [ESI+24-32], MM6;
+                cmp ESI, EDI;
+                jb startsubrmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(value - *bptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinSliceAssign_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] = 6 - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(6 - b[i]))
+                {
+                    printf("[%d]: %d != 6 - %d\n", i, c[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_a(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_g(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_h(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_g(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_g(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 5756% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 8;
+                startsublsse2u:
+                    add ESI, 64;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM2, [EAX+32];
+                    movdqu XMM3, [EAX+48];
+                    add EAX, 64;
+                    movdqu XMM4, [ECX];
+                    movdqu XMM5, [ECX+16];
+                    movdqu XMM6, [ECX+32];
+                    movdqu XMM7, [ECX+48];
+                    add ECX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM5;
+                    psubb XMM2, XMM6;
+                    psubb XMM3, XMM7;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsublsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 8;
+                startsublsse2a:
+                    add ESI, 64;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM2, [EAX+32];
+                    movdqa XMM3, [EAX+48];
+                    add EAX, 64;
+                    movdqa XMM4, [ECX];
+                    movdqa XMM5, [ECX+16];
+                    movdqa XMM6, [ECX+32];
+                    movdqa XMM7, [ECX+48];
+                    add ECX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM5;
+                    psubb XMM2, XMM6;
+                    psubb XMM3, XMM7;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsublsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 4428% faster
+        if (mmx() && a.length >= 32)
+        {
+            auto n = aptr + (a.length & ~31);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 8;
+            startsublmmx:
+                add ESI, 32;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                add EAX, 32;
+                movq MM4, [ECX];
+                movq MM5, [ECX+8];
+                movq MM6, [ECX+16];
+                movq MM7, [ECX+24];
+                add ECX, 32;
+                psubb MM0, MM4;
+                psubb MM1, MM5;
+                psubb MM2, MM6;
+                psubb MM3, MM7;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startsublmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ - *cptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= value
+ */
+
+T[] _arrayExpSliceMinass_a(T[] a, T value)
+{
+    return _arrayExpSliceMinass_g(a, value);
+}
+
+T[] _arrayExpSliceMinass_h(T[] a, T value)
+{
+    return _arrayExpSliceMinass_g(a, value);
+}
+
+T[] _arrayExpSliceMinass_g(T[] a, T value)
+{
+    //printf("_arrayExpSliceMinass_g(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1577% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+            l |= (l << 16);
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubasssse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM2, [ESI+32];
+                    movdqu XMM3, [ESI+48];
+                    add ESI, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM4;
+                    psubb XMM2, XMM4;
+                    psubb XMM3, XMM4;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubasssse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 8;
+                startsubasssse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM2, [ESI+32];
+                    movdqa XMM3, [ESI+48];
+                    add ESI, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM4;
+                    psubb XMM2, XMM4;
+                    psubb XMM3, XMM4;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubasssse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 1577% faster
+        if (mmx() && a.length >= 32)
+        {
+
+            auto n = aptr + (a.length & ~31);
+
+            uint l = cast(ubyte) value;
+            l |= (l << 8);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 8;
+            startsubassmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                add ESI, 32;
+                psubb MM0, MM4;
+                psubb MM1, MM4;
+                psubb MM2, MM4;
+                psubb MM3, MM4;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startsubassmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[]
+ */
+
+T[] _arraySliceSliceMinass_a(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_g(a, b);
+}
+
+T[] _arraySliceSliceMinass_h(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_g(a, b);
+}
+
+T[] _arraySliceSliceMinass_g(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMinass_g()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 4800% faster
+        if (sse2() && a.length >= 64)
+        {
+            auto n = aptr + (a.length & ~63);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 8;
+                startsubasslsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM2, [ESI+32];
+                    movdqu XMM3, [ESI+48];
+                    add ESI, 64;
+                    movdqu XMM4, [ECX];
+                    movdqu XMM5, [ECX+16];
+                    movdqu XMM6, [ECX+32];
+                    movdqu XMM7, [ECX+48];
+                    add ECX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM5;
+                    psubb XMM2, XMM6;
+                    psubb XMM3, XMM7;
+                    movdqu [ESI   -64], XMM0;
+                    movdqu [ESI+16-64], XMM1;
+                    movdqu [ESI+32-64], XMM2;
+                    movdqu [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubasslsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 8;
+                startsubasslsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM2, [ESI+32];
+                    movdqa XMM3, [ESI+48];
+                    add ESI, 64;
+                    movdqa XMM4, [ECX];
+                    movdqa XMM5, [ECX+16];
+                    movdqa XMM6, [ECX+32];
+                    movdqa XMM7, [ECX+48];
+                    add ECX, 64;
+                    psubb XMM0, XMM4;
+                    psubb XMM1, XMM5;
+                    psubb XMM2, XMM6;
+                    psubb XMM3, XMM7;
+                    movdqa [ESI   -64], XMM0;
+                    movdqa [ESI+16-64], XMM1;
+                    movdqa [ESI+32-64], XMM2;
+                    movdqa [ESI+48-64], XMM3;
+                    cmp ESI, EDI;
+                    jb startsubasslsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 3107% faster
+        if (mmx() && a.length >= 32)
+        {
+
+            auto n = aptr + (a.length & ~31);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 8;
+            startsubasslmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                add ESI, 32;
+                movq MM4, [ECX];
+                movq MM5, [ECX+8];
+                movq MM6, [ECX+16];
+                movq MM7, [ECX+24];
+                add ECX, 32;
+                psubb MM0, MM4;
+                psubb MM1, MM5;
+                psubb MM2, MM6;
+                psubb MM3, MM7;
+                movq [ESI   -32], MM0;
+                movq [ESI+8 -32], MM1;
+                movq [ESI+16-32], MM2;
+                movq [ESI+24-32], MM3;
+                cmp ESI, EDI;
+                jb startsubasslmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinass_g unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/arraycast.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,94 @@
+/**
+ * Implementation of array cast support routines.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arraycast;
+
+/******************************************
+ * Runtime helper to convert dynamic array of one
+ * type to dynamic array of another.
+ * Adjusts the length of the array.
+ * Throws exception if new length is not aligned.
+ */
+
+extern (C)
+
+void[] _d_arraycast(size_t tsize, size_t fsize, void[] a)
+{
+    auto length = a.length;
+
+    auto nbytes = length * fsize;
+    if (nbytes % tsize != 0)
+    {
+    throw new Exception("array cast misalignment");
+    }
+    length = nbytes / tsize;
+    *cast(size_t *)&a = length; // jam new length
+    return a;
+}
+
+unittest
+{
+    byte[int.sizeof * 3] b;
+    int[] i;
+    short[] s;
+
+    i = cast(int[])b;
+    assert(i.length == 3);
+
+    s = cast(short[])b;
+    assert(s.length == 6);
+
+    s = cast(short[])i;
+    assert(s.length == 6);
+}
+
+/******************************************
+ * Runtime helper to convert dynamic array of bits
+ * dynamic array of another.
+ * Adjusts the length of the array.
+ * Throws exception if new length is not aligned.
+ */
+
+version (none)
+{
+extern (C)
+
+void[] _d_arraycast_frombit(uint tsize, void[] a)
+{
+    uint length = a.length;
+
+    if (length & 7)
+    {
+    throw new Exception("bit[] array cast misalignment");
+    }
+    length /= 8 * tsize;
+    *cast(size_t *)&a = length; // jam new length
+    return a;
+}
+
+unittest
+{
+    version (D_Bits)
+    {
+    bit[int.sizeof * 3 * 8] b;
+    int[] i;
+    short[] s;
+
+    i = cast(int[])b;
+    assert(i.length == 3);
+
+    s = cast(short[])b;
+    assert(s.length == 6);
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/arraycat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,42 @@
+/**
+ * Implementation of array copy support routines.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arraycat;
+
+private
+{
+    import core.stdc.string;
+    debug import core.stdc.stdio;
+}
+
+extern (C):
+
+byte[] _d_arraycopy(size_t size, byte[] from, byte[] to)
+{
+    debug printf("f = %p,%d, t = %p,%d, size = %d\n",
+                 from.ptr, from.length, to.ptr, to.length, size);
+
+    if (to.length != from.length)
+    {
+        throw new Exception("lengths don't match for array copy");
+    }
+    else if (to.ptr + to.length * size <= from.ptr ||
+             from.ptr + from.length * size <= to.ptr)
+    {
+        memcpy(to.ptr, from.ptr, to.length * size);
+    }
+    else
+    {
+        throw new Exception("overlapping array copy");
+    }
+    return to;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/arraydouble.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,1720 @@
+/**
+ * Contains SSE2 and MMX versions of certain operations for double.
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arraydouble;
+
+private import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 5;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.amd3dnow amd3dnow;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+/* Performance figures measured by Burton Radons
+ */
+
+alias double T;
+
+extern (C):
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_d(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 333% faster
+        if (sse2() && b.length >= 16)
+        {
+            auto n = aptr + (b.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add ESI, 64;
+                addpd XMM0, XMM4;
+                addpd XMM1, XMM5;
+                addpd XMM2, XMM6;
+                addpd XMM3, XMM7;
+                add ECX, 64;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ = *bptr++ + *cptr++;
+
+    return a;
+}
+
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_d(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 324% faster
+        if (sse2() && b.length >= 8)
+        {
+            auto n = aptr + (b.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add ESI, 64;
+                subpd XMM0, XMM4;
+                subpd XMM1, XMM5;
+                subpd XMM2, XMM6;
+                subpd XMM3, XMM7;
+                add ECX, 64;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ = *bptr++ - *cptr++;
+
+    return a;
+}
+
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %g != %g - %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + value
+ */
+
+T[] _arraySliceExpAddSliceAssign_d(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpAddSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 305% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                addpd XMM0, XMM4;
+                addpd XMM1, XMM4;
+                addpd XMM2, XMM4;
+                addpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ + value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpAddSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %g != %g + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += value
+ */
+
+T[] _arrayExpSliceAddass_d(T[] a, T value)
+{
+    //printf("_arrayExpSliceAddass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 114% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = cast(T*)((cast(uint)aend) & ~7);
+            if (aptr < n)
+
+            // Unaligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                addpd XMM0, XMM4;
+                addpd XMM1, XMM4;
+                addpd XMM2, XMM4;
+                addpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceAddass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %g != %g + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += b[]
+ */
+
+T[] _arraySliceSliceAddass_d(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceAddass_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 183% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add ECX, 64;
+                addpd XMM0, XMM4;
+                addpd XMM1, XMM5;
+                addpd XMM2, XMM6;
+                addpd XMM3, XMM7;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - value
+ */
+
+T[] _arraySliceExpMinSliceAssign_d(T[] a, T value, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMinSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 305% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                subpd XMM0, XMM4;
+                subpd XMM1, XMM4;
+                subpd XMM2, XMM4;
+                subpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ - value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMinSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = value - b[]
+ */
+
+T[] _arrayExpSliceMinSliceAssign_d(T[] a, T[] b, T value)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arrayExpSliceMinSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 66% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movapd XMM5, XMM4;
+                movapd XMM6, XMM4;
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                subpd XMM5, XMM0;
+                subpd XMM6, XMM1;
+                movupd [ESI+ 0-64], XMM5;
+                movupd [ESI+16-64], XMM6;
+                movapd XMM5, XMM4;
+                movapd XMM6, XMM4;
+                subpd XMM5, XMM2;
+                subpd XMM6, XMM3;
+                movupd [ESI+32-64], XMM5;
+                movupd [ESI+48-64], XMM6;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = value - *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = 6 - a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(6 - a[i]))
+                {
+                    printf("[%d]: %g != 6 - %g\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= value
+ */
+
+T[] _arrayExpSliceMinass_d(T[] a, T value)
+{
+    //printf("_arrayExpSliceMinass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 115% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = cast(T*)((cast(uint)aend) & ~7);
+            if (aptr < n)
+
+            // Unaligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                subpd XMM0, XMM4;
+                subpd XMM1, XMM4;
+                subpd XMM2, XMM4;
+                subpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[]
+ */
+
+T[] _arraySliceSliceMinass_d(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMinass_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 183% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add ECX, 64;
+                subpd XMM0, XMM4;
+                subpd XMM1, XMM5;
+                subpd XMM2, XMM6;
+                subpd XMM3, XMM7;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAssign_d(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMulSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 304% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM4;
+                mulpd XMM2, XMM4;
+                mulpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * c[]
+ */
+
+T[] _arraySliceSliceMulSliceAssign_d(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceMulSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 329% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add ESI, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add EAX, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM5;
+                mulpd XMM2, XMM6;
+                mulpd XMM3, XMM7;
+                add ECX, 64;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * *cptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * b[i]))
+                {
+                    printf("[%d]: %g != %g * %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= value
+ */
+
+T[] _arrayExpSliceMulass_d(T[] a, T value)
+{
+    //printf("_arrayExpSliceMulass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 109% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = cast(T*)((cast(uint)aend) & ~7);
+            if (aptr < n)
+
+            // Unaligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, value;
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM4;
+                mulpd XMM2, XMM4;
+                mulpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= b[]
+ */
+
+T[] _arraySliceSliceMulass_d(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMulass_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 205% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                movupd XMM4, [ECX];
+                movupd XMM5, [ECX+16];
+                movupd XMM6, [ECX+32];
+                movupd XMM7, [ECX+48];
+                add ECX, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM5;
+                mulpd XMM2, XMM6;
+                mulpd XMM3, XMM7;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] / value
+ */
+
+T[] _arraySliceExpDivSliceAssign_d(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpDivSliceAssign_d()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    /* Multiplying by the reciprocal is faster, but does
+     * not produce as accurate an answer.
+     */
+    T recip = cast(T)1 / value;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 299% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, recip;
+                //movsd XMM4, value
+                //rcpsd XMM4, XMM4
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movupd XMM0, [EAX];
+                movupd XMM1, [EAX+16];
+                movupd XMM2, [EAX+32];
+                movupd XMM3, [EAX+48];
+                add EAX, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM4;
+                mulpd XMM2, XMM4;
+                mulpd XMM3, XMM4;
+                //divpd XMM0, XMM4;
+                //divpd XMM1, XMM4;
+                //divpd XMM2, XMM4;
+                //divpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+    {
+        *aptr++ = *bptr++ / value;
+        //*aptr++ = *bptr++ * recip;
+    }
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpDivSliceAssign_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] / 8;
+
+            for (int i = 0; i < dim; i++)
+            {
+                //printf("[%d]: %g ?= %g / 8\n", i, c[i], a[i]);
+                if (c[i] != cast(T)(a[i] / 8))
+                {
+                    printf("[%d]: %g != %g / 8\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] /= value
+ */
+
+T[] _arrayExpSliceDivass_d(T[] a, T value)
+{
+    //printf("_arrayExpSliceDivass_d(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    /* Multiplying by the reciprocal is faster, but does
+     * not produce as accurate an answer.
+     */
+    T recip = cast(T)1 / value;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 version is 65% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            // Unaligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movsd XMM4, recip;
+                //movsd XMM4, value
+                //rcpsd XMM4, XMM4
+                shufpd XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movupd XMM0, [ESI];
+                movupd XMM1, [ESI+16];
+                movupd XMM2, [ESI+32];
+                movupd XMM3, [ESI+48];
+                add ESI, 64;
+                mulpd XMM0, XMM4;
+                mulpd XMM1, XMM4;
+                mulpd XMM2, XMM4;
+                mulpd XMM3, XMM4;
+                //divpd XMM0, XMM4;
+                //divpd XMM1, XMM4;
+                //divpd XMM2, XMM4;
+                //divpd XMM3, XMM4;
+                movupd [ESI+ 0-64], XMM0;
+                movupd [ESI+16-64], XMM1;
+                movupd [ESI+32-64], XMM2;
+                movupd [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= recip;
+
+    return a;
+}
+
+
+unittest
+{
+    printf("_arrayExpSliceDivass_d unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] /= 8;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] / 8))
+                {
+                    printf("[%d]: %g != %g / 8\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[] * value
+ */
+
+T[] _arraySliceExpMulSliceMinass_d(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAddass_d(a, -value, b);
+}
+
+/***********************
+ * Computes:
+ *      a[] += b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAddass_d(T[] a, T value, T[] b)
+in
+{
+        assert(a.length == b.length);
+        assert(disjoint(a, b));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ += *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAddass_d unittest\n");
+
+    cpuid = 1;
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 1; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] += a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                //printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]);
+                if (c[i] != cast(T)(b[i] + a[i] * 6))
+                {
+                    printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/arrayfloat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,2309 @@
+/**
+ * Contains SSE2 and MMX versions of certain operations for float.
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arrayfloat;
+
+private import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 5;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.amd3dnow amd3dnow;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+alias float T;
+
+extern (C):
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_f(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceAddSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 834% faster
+        if (sse() && b.length >= 16)
+        {
+            version (log) printf("\tsse unaligned\n");
+            auto n = aptr + (b.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add ESI, 64;
+                addps XMM0, XMM4;
+                addps XMM1, XMM5;
+                addps XMM2, XMM6;
+                addps XMM3, XMM7;
+                add ECX, 64;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is only 13% faster
+        if (amd3dnow() && b.length >= 8)
+        {
+            version (log) printf("\tamd3dnow\n");
+            auto n = aptr + (b.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+
+                align 4;
+            start3dnow:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfadd MM0, [ECX];
+                pfadd MM1, [ECX+8];
+                pfadd MM2, [ECX+16];
+                pfadd MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ECX, 32;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    // Handle remainder
+    version (log) if (aptr < aend) printf("\tbase\n");
+    while (aptr < aend)
+        *aptr++ = *bptr++ + *cptr++;
+
+    return a;
+}
+
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_f(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 834% faster
+        if (sse() && b.length >= 16)
+        {
+            auto n = aptr + (b.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add ESI, 64;
+                subps XMM0, XMM4;
+                subps XMM1, XMM5;
+                subps XMM2, XMM6;
+                subps XMM3, XMM7;
+                add ECX, 64;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is only 13% faster
+        if (amd3dnow() && b.length >= 8)
+        {
+            auto n = aptr + (b.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr; // destination operand
+                mov EDI, n;    // end comparison
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+
+                align 4;
+            start3dnow:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfsub MM0, [ECX];
+                pfsub MM1, [ECX+8];
+                pfsub MM2, [ECX+16];
+                pfsub MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ECX, 32;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ = *bptr++ - *cptr++;
+
+    return a;
+}
+
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %g != %gd - %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + value
+ */
+
+T[] _arraySliceExpAddSliceAssign_f(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpAddSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 665% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                addps XMM0, XMM4;
+                addps XMM1, XMM4;
+                addps XMM2, XMM4;
+                addps XMM3, XMM4;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        // 3DNow! version is 69% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start3dnow:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfadd MM0, MM4;
+                pfadd MM1, MM4;
+                pfadd MM2, MM4;
+                pfadd MM3, MM4;
+                movq [ESI],    MM0;
+                movq [ESI+8],  MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ + value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpAddSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %g != %g + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += value
+ */
+
+T[] _arrayExpSliceAddass_f(T[] a, T value)
+{
+    //printf("_arrayExpSliceAddass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 302% faster
+        if (sse() && a.length >= 16)
+        {
+            // align pointer
+            auto n = cast(T*)((cast(uint)aptr + 15) & ~15);
+            while (aptr < n)
+                *aptr++ += value;
+            n = cast(T*)((cast(uint)aend) & ~15);
+            if (aptr < n)
+
+            // Aligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movaps XMM0, [ESI];
+                movaps XMM1, [ESI+16];
+                movaps XMM2, [ESI+32];
+                movaps XMM3, [ESI+48];
+                add ESI, 64;
+                addps XMM0, XMM4;
+                addps XMM1, XMM4;
+                addps XMM2, XMM4;
+                addps XMM3, XMM4;
+                movaps [ESI+ 0-64], XMM0;
+                movaps [ESI+16-64], XMM1;
+                movaps [ESI+32-64], XMM2;
+                movaps [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+        else
+        // 3DNow! version is 63% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start3dnow:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfadd MM0, MM4;
+                pfadd MM1, MM4;
+                pfadd MM2, MM4;
+                pfadd MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceAddass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %g != %g + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += b[]
+ */
+
+T[] _arraySliceSliceAddass_f(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceAddass_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 468% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [ESI];
+                movups XMM1, [ESI+16];
+                movups XMM2, [ESI+32];
+                movups XMM3, [ESI+48];
+                add ESI, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add ECX, 64;
+                addps XMM0, XMM4;
+                addps XMM1, XMM5;
+                addps XMM2, XMM6;
+                addps XMM3, XMM7;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is 57% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr]; // destination operand
+                mov EDI, dword ptr [n];    // end comparison
+                mov ECX, dword ptr [bptr]; // right operand
+
+                align 4;
+            start3dnow:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfadd MM0, [ECX];
+                pfadd MM1, [ECX+8];
+                pfadd MM2, [ECX+16];
+                pfadd MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add ECX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+                mov dword ptr [bptr], ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] += b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %g != %g + %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - value
+ */
+
+T[] _arraySliceExpMinSliceAssign_f(T[] a, T value, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMinSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 622% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                subps XMM0, XMM4;
+                subps XMM1, XMM4;
+                subps XMM2, XMM4;
+                subps XMM3, XMM4;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        // 3DNow! version is 67% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            T[2] w;
+
+            w[0] = w[1] = value;
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                mov EAX, dword ptr [bptr];
+                movq MM4, qword ptr [w];
+
+                align 8;
+            start3dnow:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfsub MM0, MM4;
+                pfsub MM1, MM4;
+                pfsub MM2, MM4;
+                pfsub MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+                mov dword ptr [bptr], EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ - value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMinSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = value - b[]
+ */
+
+T[] _arrayExpSliceMinSliceAssign_f(T[] a, T[] b, T value)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arrayExpSliceMinSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 690% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movaps XMM5, XMM4;
+                movaps XMM6, XMM4;
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                subps XMM5, XMM0;
+                subps XMM6, XMM1;
+                movups [ESI+ 0-64], XMM5;
+                movups [ESI+16-64], XMM6;
+                movaps XMM5, XMM4;
+                movaps XMM6, XMM4;
+                subps XMM5, XMM2;
+                subps XMM6, XMM3;
+                movups [ESI+32-64], XMM5;
+                movups [ESI+48-64], XMM6;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        // 3DNow! version is 67% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start3dnow:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfsubr MM0, MM4;
+                pfsubr MM1, MM4;
+                pfsubr MM2, MM4;
+                pfsubr MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start3dnow;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = value - *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = 6 - a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(6 - a[i]))
+                {
+                    printf("[%d]: %g != 6 - %g\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= value
+ */
+
+T[] _arrayExpSliceMinass_f(T[] a, T value)
+{
+    //printf("_arrayExpSliceMinass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 304% faster
+        if (sse() && a.length >= 16)
+        {
+            // align pointer
+            auto n = cast(T*)((cast(uint)aptr + 15) & ~15);
+            while (aptr < n)
+                *aptr++ -= value;
+            n = cast(T*)((cast(uint)aend) & ~15);
+            if (aptr < n)
+
+            // Aligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movaps XMM0, [ESI];
+                movaps XMM1, [ESI+16];
+                movaps XMM2, [ESI+32];
+                movaps XMM3, [ESI+48];
+                add ESI, 64;
+                subps XMM0, XMM4;
+                subps XMM1, XMM4;
+                subps XMM2, XMM4;
+                subps XMM3, XMM4;
+                movaps [ESI+ 0-64], XMM0;
+                movaps [ESI+16-64], XMM1;
+                movaps [ESI+32-64], XMM2;
+                movaps [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+        else
+        // 3DNow! version is 63% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfsub MM0, MM4;
+                pfsub MM1, MM4;
+                pfsub MM2, MM4;
+                pfsub MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceminass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[]
+ */
+
+T[] _arraySliceSliceMinass_f(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMinass_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 468% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [ESI];
+                movups XMM1, [ESI+16];
+                movups XMM2, [ESI+32];
+                movups XMM3, [ESI+48];
+                add ESI, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add ECX, 64;
+                subps XMM0, XMM4;
+                subps XMM1, XMM5;
+                subps XMM2, XMM6;
+                subps XMM3, XMM7;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is 57% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr]; // destination operand
+                mov EDI, dword ptr [n]; // end comparison
+                mov ECX, dword ptr [bptr]; // right operand
+
+                align 4;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfsub MM0, [ECX];
+                pfsub MM1, [ECX+8];
+                pfsub MM2, [ECX+16];
+                pfsub MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add ECX, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %g != %g - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAssign_f(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMulSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 607% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM4;
+                mulps XMM2, XMM4;
+                mulps XMM3, XMM4;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        // 3DNow! version is 69% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                mov EAX, dword ptr [bptr];
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfmul MM0, MM4;
+                pfmul MM1, MM4;
+                pfmul MM2, MM4;
+                pfmul MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * c[]
+ */
+
+T[] _arraySliceSliceMulSliceAssign_f(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceMulSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 833% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr; // left operand
+                mov ECX, cptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add ESI, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add EAX, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM5;
+                mulps XMM2, XMM6;
+                mulps XMM3, XMM7;
+                add ECX, 64;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is only 13% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr]; // destination operand
+                mov EDI, dword ptr [n]; // end comparison
+                mov EAX, dword ptr [bptr]; // left operand
+                mov ECX, dword ptr [cptr]; // right operand
+
+                align 4;
+            start:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfmul MM0, [ECX];
+                pfmul MM1, [ECX+8];
+                pfmul MM2, [ECX+16];
+                pfmul MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ECX, 32;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * *cptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * b[i]))
+                {
+                    printf("[%d]: %g != %g * %g\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= value
+ */
+
+T[] _arrayExpSliceMulass_f(T[] a, T value)
+{
+    //printf("_arrayExpSliceMulass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 303% faster
+        if (sse() && a.length >= 16)
+        {
+            // align pointer
+            auto n = cast(T*)((cast(uint)aptr + 15) & ~15);
+            while (aptr < n)
+                *aptr++ *= value;
+            n = cast(T*)((cast(uint)aend) & ~15);
+            if (aptr < n)
+
+            // Aligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, value;
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movaps XMM0, [ESI];
+                movaps XMM1, [ESI+16];
+                movaps XMM2, [ESI+32];
+                movaps XMM3, [ESI+48];
+                add ESI, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM4;
+                mulps XMM2, XMM4;
+                mulps XMM3, XMM4;
+                movaps [ESI+ 0-64], XMM0;
+                movaps [ESI+16-64], XMM1;
+                movaps [ESI+32-64], XMM2;
+                movaps [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+        else
+        // 3DNow! version is 63% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            ulong w = *cast(uint *) &value;
+            ulong v = w | (w << 32L);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                movq MM4, qword ptr [v];
+
+                align 8;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfmul MM0, MM4;
+                pfmul MM1, MM4;
+                pfmul MM2, MM4;
+                pfmul MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= b[]
+ */
+
+T[] _arraySliceSliceMulass_f(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMulass_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 525% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov ECX, bptr; // right operand
+                mov ESI, aptr; // destination operand
+                mov EDI, n; // end comparison
+
+                align 8;
+            startsseloopb:
+                movups XMM0, [ESI];
+                movups XMM1, [ESI+16];
+                movups XMM2, [ESI+32];
+                movups XMM3, [ESI+48];
+                add ESI, 64;
+                movups XMM4, [ECX];
+                movups XMM5, [ECX+16];
+                movups XMM6, [ECX+32];
+                movups XMM7, [ECX+48];
+                add ECX, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM5;
+                mulps XMM2, XMM6;
+                mulps XMM3, XMM7;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopb;
+
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+        else
+        // 3DNow! version is 57% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, dword ptr [aptr]; // destination operand
+                mov EDI, dword ptr [n]; // end comparison
+                mov ECX, dword ptr [bptr]; // right operand
+
+                align 4;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfmul MM0, [ECX];
+                pfmul MM1, [ECX+8];
+                pfmul MM2, [ECX+16];
+                pfmul MM3, [ECX+24];
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add ECX, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+                mov dword ptr [bptr], ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %g != %g * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] / value
+ */
+
+T[] _arraySliceExpDivSliceAssign_f(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpDivSliceAssign_f()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    /* Multiplying by the reciprocal is faster, but does
+     * not produce as accurate an answer.
+     */
+    T recip = cast(T)1 / value;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 587% faster
+        if (sse() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            // Unaligned case
+            asm
+            {
+                mov EAX, bptr;
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, recip;
+                //movss XMM4, value
+                //rcpss XMM4, XMM4
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloop:
+                add ESI, 64;
+                movups XMM0, [EAX];
+                movups XMM1, [EAX+16];
+                movups XMM2, [EAX+32];
+                movups XMM3, [EAX+48];
+                add EAX, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM4;
+                mulps XMM2, XMM4;
+                mulps XMM3, XMM4;
+                //divps XMM0, XMM4;
+                //divps XMM1, XMM4;
+                //divps XMM2, XMM4;
+                //divps XMM3, XMM4;
+                movups [ESI+ 0-64], XMM0;
+                movups [ESI+16-64], XMM1;
+                movups [ESI+32-64], XMM2;
+                movups [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloop;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        // 3DNow! version is 72% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            T[2] w = void;
+
+            w[0] = recip;
+            w[1] = recip;
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                mov EAX, dword ptr [bptr];
+                movq MM4, qword ptr [w];
+
+                align 8;
+            start:
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                movq MM2, [EAX+16];
+                movq MM3, [EAX+24];
+                pfmul MM0, MM4;
+                pfmul MM1, MM4;
+                pfmul MM2, MM4;
+                pfmul MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                add EAX, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+                mov dword ptr [bptr], EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * recip;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpDivSliceAssign_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] / 8;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] / 8))
+                {
+                    printf("[%d]: %g != %g / 8\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] /= value
+ */
+
+T[] _arrayExpSliceDivass_f(T[] a, T value)
+{
+    //printf("_arrayExpSliceDivass_f(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    /* Multiplying by the reciprocal is faster, but does
+     * not produce as accurate an answer.
+     */
+    T recip = cast(T)1 / value;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE version is 245% faster
+        if (sse() && a.length >= 16)
+        {
+            // align pointer
+            auto n = cast(T*)((cast(uint)aptr + 15) & ~15);
+            while (aptr < n)
+                *aptr++ *= recip;
+            n = cast(T*)((cast(uint)aend) & ~15);
+            if (aptr < n)
+
+            // Aligned case
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movss XMM4, recip;
+                //movss XMM4, value
+                //rcpss XMM4, XMM4
+                shufps XMM4, XMM4, 0;
+
+                align 8;
+            startsseloopa:
+                movaps XMM0, [ESI];
+                movaps XMM1, [ESI+16];
+                movaps XMM2, [ESI+32];
+                movaps XMM3, [ESI+48];
+                add ESI, 64;
+                mulps XMM0, XMM4;
+                mulps XMM1, XMM4;
+                mulps XMM2, XMM4;
+                mulps XMM3, XMM4;
+                //divps XMM0, XMM4;
+                //divps XMM1, XMM4;
+                //divps XMM2, XMM4;
+                //divps XMM3, XMM4;
+                movaps [ESI+ 0-64], XMM0;
+                movaps [ESI+16-64], XMM1;
+                movaps [ESI+32-64], XMM2;
+                movaps [ESI+48-64], XMM3;
+                cmp ESI, EDI;
+                jb startsseloopa;
+
+                mov aptr, ESI;
+            }
+        }
+        else
+        // 3DNow! version is 57% faster
+        if (amd3dnow() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            T[2] w = void;
+
+            w[0] = w[1] = recip;
+
+            asm
+            {
+                mov ESI, dword ptr [aptr];
+                mov EDI, dword ptr [n];
+                movq MM4, qword ptr [w];
+
+                align 8;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                movq MM2, [ESI+16];
+                movq MM3, [ESI+24];
+                pfmul MM0, MM4;
+                pfmul MM1, MM4;
+                pfmul MM2, MM4;
+                pfmul MM3, MM4;
+                movq [ESI], MM0;
+                movq [ESI+8], MM1;
+                movq [ESI+16], MM2;
+                movq [ESI+24], MM3;
+                add ESI, 32;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov dword ptr [aptr], ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= recip;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceDivass_f unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            c[] /= 8;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] / 8))
+                {
+                    printf("[%d]: %g != %g / 8\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[] * value
+ */
+
+T[] _arraySliceExpMulSliceMinass_f(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAddass_f(a, -value, b);
+}
+
+/***********************
+ * Computes:
+ *      a[] += b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAddass_f(T[] a, T value, T[] b)
+in
+{
+        assert(a.length == b.length);
+        assert(disjoint(a, b));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ += *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAddass_f unittest\n");
+
+    cpuid = 1;
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 1; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] += a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                //printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]);
+                if (c[i] != cast(T)(b[i] + a[i] * 6))
+                {
+                    printf("[%d]: %g ?= %g + %g * 6\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/arrayint.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,2430 @@
+/**
+ * Contains MMX versions of certain operations for dchar, int, and uint ('w',
+ * 'i' and 'k' suffixes).
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arrayint;
+
+private import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 4;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.amd3dnow amd3dnow;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+alias int T;
+
+extern (C):
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + value
+ */
+
+T[] _arraySliceExpAddSliceAssign_w(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_k(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_i(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpAddSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 380% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 298% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                paddd MM0, MM2;
+                paddd MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        if (a.length >= 2)
+        {
+            auto n = aptr + (a.length & ~1);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov EDX, value;
+
+                align 4;
+            start386:
+                add ESI, 8;
+                mov EBX, [EAX];
+                mov ECX, [EAX+4];
+                add EAX, 8;
+                add EBX, EDX;
+                add ECX, EDX;
+                mov [ESI  -8], EBX;
+                mov [ESI+4-8], ECX;
+                cmp ESI, EDI;
+                jb start386;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ + value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpAddSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_w(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_k(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_i(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceAddSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1710% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 995% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM2, [ECX];
+                movq MM1, [EAX+8];
+                movq MM3, [ECX+8];
+                add EAX, 16;
+                add ECX, 16;
+                paddd MM0, MM2;
+                paddd MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+normal:
+    while (aptr < aend)
+        *aptr++ = *bptr++ + *cptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += value
+ */
+
+T[] _arrayExpSliceAddass_w(T[] a, T value)
+{
+    return _arrayExpSliceAddass_i(a, value);
+}
+
+T[] _arrayExpSliceAddass_k(T[] a, T value)
+{
+    return _arrayExpSliceAddass_i(a, value);
+}
+
+T[] _arrayExpSliceAddass_i(T[] a, T value)
+{
+    //printf("_arrayExpSliceAddass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 83% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 81% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                paddd MM0, MM2;
+                paddd MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+        else
+        if (a.length >= 2)
+        {
+            auto n = aptr + (a.length & ~1);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EDX, value;
+
+                align 4;
+            start386:
+                mov EBX, [ESI];
+                mov ECX, [ESI+4];
+                add ESI, 8;
+                add EBX, EDX;
+                add ECX, EDX;
+                mov [ESI  -8], EBX;
+                mov [ESI+4-8], ECX;
+                cmp ESI, EDI;
+                jb start386;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceAddass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            a[] += 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(c[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, a[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += b[]
+ */
+
+T[] _arraySliceSliceAddass_w(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_i(a, b);
+}
+
+T[] _arraySliceSliceAddass_k(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_i(a, b);
+}
+
+T[] _arraySliceSliceAddass_i(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceAddass_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 695% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    paddd XMM0, XMM2;
+                    paddd XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 471% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM2, [ECX];
+                movq MM1, [ESI+8];
+                movq MM3, [ECX+8];
+                add ESI, 16;
+                add ECX, 16;
+                paddd MM0, MM2;
+                paddd MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+normal:
+    while (aptr < aend)
+        *aptr++ += *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] += a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(b[i] + a[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - value
+ */
+
+T[] _arraySliceExpMinSliceAssign_w(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_k(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_i(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMinSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 400% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 315% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                psubd MM0, MM2;
+                psubd MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+        else
+        if (a.length >= 2)
+        {
+            auto n = aptr + (a.length & ~1);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov EDX, value;
+
+                align 4;
+            start386:
+                add ESI, 8;
+                mov EBX, [EAX];
+                mov ECX, [EAX+4];
+                add EAX, 8;
+                sub EBX, EDX;
+                sub ECX, EDX;
+                mov [ESI  -8], EBX;
+                mov [ESI+4-8], ECX;
+                cmp ESI, EDI;
+                jb start386;
+
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ - value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMinSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = value - b[]
+ */
+
+T[] _arrayExpSliceMinSliceAssign_w(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_i(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_k(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_i(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_i(T[] a, T[] b, T value)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arrayExpSliceMinSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1812% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 4;
+                startaddsse2u:
+                    add ESI, 32;
+                    movdqu XMM2, [EAX];
+                    movdqu XMM3, [EAX+16];
+                    movdqa XMM0, XMM4;
+                    movdqa XMM1, XMM4;
+                    add EAX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM4, l;
+                    pshufd XMM4, XMM4, 0;
+
+                    align 4;
+                startaddsse2a:
+                    add ESI, 32;
+                    movdqa XMM2, [EAX];
+                    movdqa XMM3, [EAX+16];
+                    movdqa XMM0, XMM4;
+                    movdqa XMM1, XMM4;
+                    add EAX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 1077% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM4, l;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM2, [EAX];
+                movq MM3, [EAX+8];
+                movq MM0, MM4;
+                movq MM1, MM4;
+                add EAX, 16;
+                psubd MM0, MM2;
+                psubd MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = value - *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = 6 - a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(6 - a[i]))
+                {
+                    printf("[%d]: %d != 6 - %d\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_w(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_k(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_i(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1721% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 1002% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM2, [ECX];
+                movq MM1, [EAX+8];
+                movq MM3, [ECX+8];
+                add EAX, 16;
+                add ECX, 16;
+                psubd MM0, MM2;
+                psubd MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ - *cptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= value
+ */
+
+T[] _arrayExpSliceMinass_w(T[] a, T value)
+{
+    return _arrayExpSliceMinass_i(a, value);
+}
+
+T[] _arrayExpSliceMinass_k(T[] a, T value)
+{
+    return _arrayExpSliceMinass_i(a, value);
+}
+
+T[] _arrayExpSliceMinass_i(T[] a, T value)
+{
+    //printf("_arrayExpSliceMinass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 81% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 81% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                psubd MM0, MM2;
+                psubd MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+        else
+        if (a.length >= 2)
+        {
+            auto n = aptr + (a.length & ~1);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EDX, value;
+
+                align 4;
+            start386:
+                mov EBX, [ESI];
+                mov ECX, [ESI+4];
+                add ESI, 8;
+                sub EBX, EDX;
+                sub ECX, EDX;
+                mov [ESI  -8], EBX;
+                mov [ESI+4-8], ECX;
+                cmp ESI, EDI;
+                jb start386;
+
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            a[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(c[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, a[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[]
+ */
+
+T[] _arraySliceSliceMinass_w(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_i(a, b);
+}
+
+T[] _arraySliceSliceMinass_k(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_i(a, b);
+}
+
+T[] _arraySliceSliceMinass_i(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMinass_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 731% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    psubd XMM0, XMM2;
+                    psubd XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 441% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM2, [ECX];
+                movq MM1, [ESI+8];
+                movq MM3, [ECX+8];
+                add ESI, 16;
+                add ECX, 16;
+                psubd MM0, MM2;
+                psubd MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] -= a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(b[i] - a[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAssign_w(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpMulSliceAssign_k(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAssign_i(a, value, b);
+}
+
+T[] _arraySliceExpMulSliceAssign_i(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMulSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+  version (none)        // multiplying a pair is not supported by MMX
+  {
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1380% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        {
+        // MMX version is 1380% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                pmuludq MM0, MM2;       // only multiplies low 32 bits
+                pmuludq MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+        }
+  }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                //printf("[%d]: %d ?= %d * 6\n", i, c[i], a[i]);
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %d != %d * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * c[]
+ */
+
+T[] _arraySliceSliceMulSliceAssign_w(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMulSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceMulSliceAssign_k(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMulSliceAssign_i(a, c, b);
+}
+
+T[] _arraySliceSliceMulSliceAssign_i(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceMulSliceAssign_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+  version (none)
+  {
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 1407% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+               }
+            }
+        }
+        else
+        // MMX version is 1029% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM2, [ECX];
+                movq MM1, [EAX+8];
+                movq MM3, [ECX+8];
+                add EAX, 16;
+                add ECX, 16;
+                pmuludq MM0, MM2;
+                pmuludq MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+  }
+
+    while (aptr < aend)
+        *aptr++ = *bptr++ * *cptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulSliceAssign_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * b[i]))
+                {
+                    printf("[%d]: %d != %d * %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= value
+ */
+
+T[] _arrayExpSliceMulass_w(T[] a, T value)
+{
+    return _arrayExpSliceMulass_i(a, value);
+}
+
+T[] _arrayExpSliceMulass_k(T[] a, T value)
+{
+    return _arrayExpSliceMulass_i(a, value);
+}
+
+T[] _arrayExpSliceMulass_i(T[] a, T value)
+{
+    //printf("_arrayExpSliceMulass_i(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+  version (none)
+  {
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 400% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = value;
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 402% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            ulong l = cast(uint) value | (cast(ulong)cast(uint) value << 32);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movq MM2, l;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                pmuludq MM0, MM2;
+                pmuludq MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+  }
+
+    while (aptr < aend)
+        *aptr++ *= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = a[];
+            a[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(b[i] * 6))
+                {
+                    printf("[%d]: %d != %d * 6\n", i, a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= b[]
+ */
+
+T[] _arraySliceSliceMulass_w(T[] a, T[] b)
+{
+    return _arraySliceSliceMulass_i(a, b);
+}
+
+T[] _arraySliceSliceMulass_k(T[] a, T[] b)
+{
+    return _arraySliceSliceMulass_i(a, b);
+}
+
+T[] _arraySliceSliceMulass_i(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMulass_i()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+  version (none)
+  {
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 873% faster
+        if (sse2() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    pmuludq XMM0, XMM2;
+                    pmuludq XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+               }
+            }
+        }
+/+ BUG: comment out this section until we figure out what is going
+   wrong with the invalid pshufd instructions.
+
+        else
+        // MMX version is 573% faster
+        if (mmx() && a.length >= 4)
+        {
+            auto n = aptr + (a.length & ~3);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM2, [ECX];
+                movq MM1, [ESI+8];
+                movq MM3, [ECX+8];
+                pxor MM4, MM4;
+                pxor MM5, MM5;
+                punpckldq MM4, MM0;
+                punpckldq MM5, MM2;
+                add ESI, 16;
+                add ECX, 16;
+                pmuludq MM4, MM5;
+                pshufd MM4, MM4, 8;     // ?
+                movq [ESI  -16], MM4;
+                pxor MM4, MM4;
+                pxor MM5, MM5;
+                punpckldq MM4, MM1;
+                punpckldq MM5, MM3;
+                pmuludq MM4, MM5;
+                pshufd MM4, MM4, 8;     // ?
+                movq [ESI+8-16], MM4;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
++/
+    }
+  }
+
+    while (aptr < aend)
+        *aptr++ *= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulass_i unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = a[];
+            a[] *= c[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(b[i] * c[i]))
+                {
+                    printf("[%d]: %d != %d * %d\n", i, a[i], b[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/arrayreal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,241 @@
+/**
+ * Contains SSE2 and MMX versions of certain operations for real.
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arrayreal;
+
+import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 1;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.amd3dnow amd3dnow;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+alias real T;
+
+extern (C):
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_r(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    for (int i = 0; i < a.length; i++)
+        a[i] = b[i] + c[i];
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_r unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %Lg != %Lg + %Lg\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_r(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    for (int i = 0; i < a.length; i++)
+        a[i] = b[i] - c[i];
+    return a;
+}
+
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_r unittest\n");
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %Lg != %Lg - %Lg\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[] * value
+ */
+
+T[] _arraySliceExpMulSliceMinass_r(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAddass_r(a, -value, b);
+}
+
+/***********************
+ * Computes:
+ *      a[] += b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAddass_r(T[] a, T value, T[] b)
+in
+{
+        assert(a.length == b.length);
+        assert(disjoint(a, b));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    // Handle remainder
+    while (aptr < aend)
+        *aptr++ += *bptr++ * value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAddass_r unittest\n");
+
+    cpuid = 1;
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 1; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] += a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                //printf("[%d]: %Lg ?= %Lg + %Lg * 6\n", i, c[i], b[i], a[i]);
+                if (c[i] != cast(T)(b[i] + a[i] * 6))
+                {
+                    printf("[%d]: %Lg ?= %Lg + %Lg * 6\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/arrayshort.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,2303 @@
+/**
+ * Contains SSE2 and MMX versions of certain operations for wchar, short,
+ * and ushort ('u', 's' and 't' suffixes).
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, based on code originally written by Burton Radons
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.arrayshort;
+
+private import rt.util.cpuid;
+
+version (unittest)
+{
+    private import core.stdc.stdio : printf;
+    /* This is so unit tests will test every CPU variant
+     */
+    int cpuid;
+    const int CPUID_MAX = 4;
+    bool mmx()      { return cpuid == 1 && rt.util.cpuid.mmx(); }
+    bool sse()      { return cpuid == 2 && rt.util.cpuid.sse(); }
+    bool sse2()     { return cpuid == 3 && rt.util.cpuid.sse2(); }
+    bool amd3dnow() { return cpuid == 4 && rt.util.cpuid.amd3dnow(); }
+}
+else
+{
+    alias rt.util.cpuid.mmx mmx;
+    alias rt.util.cpuid.sse sse;
+    alias rt.util.cpuid.sse2 sse2;
+    alias rt.util.cpuid.sse2 sse2;
+}
+
+//version = log;
+
+bool disjoint(T)(T[] a, T[] b)
+{
+    return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
+}
+
+alias short T;
+
+extern (C):
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + value
+ */
+
+T[] _arraySliceExpAddSliceAssign_u(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_t(T[] a, T value, T[] b)
+{
+    return _arraySliceExpAddSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpAddSliceAssign_s(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpAddSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 3343% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 3343% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                paddw MM0, MM2;
+                paddw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ + value);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpAddSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] + c[]
+ */
+
+T[] _arraySliceSliceAddSliceAssign_u(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_t(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceAddSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceAddSliceAssign_s(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceAddSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 3777% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    movdqu XMM2, [ECX];
+                    movdqu XMM3, [ECX+16];
+                    add ECX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    movdqa XMM2, [ECX];
+                    movdqa XMM3, [ECX+16];
+                    add ECX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 2068% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                movq MM2, [ECX];
+                movq MM3, [ECX+8];
+                add ECX, 16;
+                paddw MM0, MM2;
+                paddw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ + *cptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] + b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] + b[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += value
+ */
+
+T[] _arrayExpSliceAddass_u(T[] a, T value)
+{
+    return _arrayExpSliceAddass_s(a, value);
+}
+
+T[] _arrayExpSliceAddass_t(T[] a, T value)
+{
+    return _arrayExpSliceAddass_s(a, value);
+}
+
+T[] _arrayExpSliceAddass_s(T[] a, T value)
+{
+    //printf("_arrayExpSliceAddass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 832% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= (l << 16);
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 826% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                paddw MM0, MM2;
+                paddw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceAddass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            a[] += 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(c[i] + 6))
+                {
+                    printf("[%d]: %d != %d + 6\n", i, a[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] += b[]
+ */
+
+T[] _arraySliceSliceAddass_u(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_s(a, b);
+}
+
+T[] _arraySliceSliceAddass_t(T[] a, T[] b)
+{
+    return _arraySliceSliceAddass_s(a, b);
+}
+
+T[] _arraySliceSliceAddass_s(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceAddass_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 2085% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    movdqu XMM2, [ECX];
+                    movdqu XMM3, [ECX+16];
+                    add ECX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    movdqa XMM2, [ECX];
+                    movdqa XMM3, [ECX+16];
+                    add ECX, 32;
+                    paddw XMM0, XMM2;
+                    paddw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 1022% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                movq MM2, [ECX];
+                movq MM3, [ECX+8];
+                add ECX, 16;
+                paddw MM0, MM2;
+                paddw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ += *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceAddass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] += a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(b[i] + a[i]))
+                {
+                    printf("[%d]: %d != %d + %d\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - value
+ */
+
+T[] _arraySliceExpMinSliceAssign_u(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_t(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMinSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpMinSliceAssign_s(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMinSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 3695% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 3049% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                psubw MM0, MM2;
+                psubw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ - value);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMinSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = value - b[]
+ */
+
+T[] _arrayExpSliceMinSliceAssign_u(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_s(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_t(T[] a, T[] b, T value)
+{
+    return _arrayExpSliceMinSliceAssign_s(a, b, value);
+}
+
+T[] _arrayExpSliceMinSliceAssign_s(T[] a, T[] b, T value)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arrayExpSliceMinSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 4995% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= (l << 16);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+
+                    align 4;
+                startaddsse2u:
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+                    movd XMM3, l;
+                    pshufd XMM3, XMM3, 0;
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubw XMM2, XMM0;
+                    psubw XMM3, XMM1;
+                    movdqu [ESI   -32], XMM2;
+                    movdqu [ESI+16-32], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+
+                    align 4;
+                startaddsse2a:
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+                    movd XMM3, l;
+                    pshufd XMM3, XMM3, 0;
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    psubw XMM2, XMM0;
+                    psubw XMM3, XMM1;
+                    movdqa [ESI   -32], XMM2;
+                    movdqa [ESI+16-32], XMM3;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 4562% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM4, l;
+                pshufw MM4, MM4, 0;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM2, [EAX];
+                movq MM3, [EAX+8];
+                movq MM0, MM4;
+                movq MM1, MM4;
+                add EAX, 16;
+                psubw MM0, MM2;
+                psubw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(value - *bptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = 6 - a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(6 - a[i]))
+                {
+                    printf("[%d]: %d != 6 - %d\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] - c[]
+ */
+
+T[] _arraySliceSliceMinSliceAssign_u(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_t(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMinSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceMinSliceAssign_s(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 4129% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    movdqu XMM2, [ECX];
+                    movdqu XMM3, [ECX+16];
+                    add ECX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    movdqa XMM2, [ECX];
+                    movdqa XMM3, [ECX+16];
+                    add ECX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 2018% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                movq MM2, [ECX];
+                movq MM3, [ECX+8];
+                add ECX, 16;
+                psubw MM0, MM2;
+                psubw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ - *cptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] - b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] - b[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= value
+ */
+
+T[] _arrayExpSliceMinass_u(T[] a, T value)
+{
+    return _arrayExpSliceMinass_s(a, value);
+}
+
+T[] _arrayExpSliceMinass_t(T[] a, T value)
+{
+    return _arrayExpSliceMinass_s(a, value);
+}
+
+T[] _arrayExpSliceMinass_s(T[] a, T value)
+{
+    //printf("_arrayExpSliceMinass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 835% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= (l << 16);
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startaddsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startaddsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 835% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                psubw MM0, MM2;
+                psubw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMinass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            a[] = c[];
+            a[] -= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(c[i] - 6))
+                {
+                    printf("[%d]: %d != %d - 6\n", i, a[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] -= b[]
+ */
+
+T[] _arraySliceSliceMinass_u(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_s(a, b);
+}
+
+T[] _arraySliceSliceMinass_t(T[] a, T[] b)
+{
+    return _arraySliceSliceMinass_s(a, b);
+}
+
+T[] _arraySliceSliceMinass_s(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMinass_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 2121% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm // unaligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    movdqu XMM2, [ECX];
+                    movdqu XMM3, [ECX+16];
+                    add ECX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm // aligned case
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    movdqa XMM2, [ECX];
+                    movdqa XMM3, [ECX+16];
+                    add ECX, 32;
+                    psubw XMM0, XMM2;
+                    psubw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+        }
+        else
+        // MMX version is 1116% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            start:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                movq MM2, [ECX];
+                movq MM3, [ECX+8];
+                add ECX, 16;
+                psubw MM0, MM2;
+                psubw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb start;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ -= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMinass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = c[];
+            c[] -= a[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(b[i] - a[i]))
+                {
+                    printf("[%d]: %d != %d - %d\n", i, c[i], b[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * value
+ */
+
+T[] _arraySliceExpMulSliceAssign_u(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpMulSliceAssign_t(T[] a, T value, T[] b)
+{
+    return _arraySliceExpMulSliceAssign_s(a, value, b);
+}
+
+T[] _arraySliceExpMulSliceAssign_s(T[] a, T value, T[] b)
+in
+{
+    assert(a.length == b.length);
+    assert(disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceExpMulSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 3733% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= l << 16;
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM1, [EAX+16];
+                    add EAX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM1, [EAX+16];
+                    add EAX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                }
+            }
+        }
+        else
+        // MMX version is 3733% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM1, [EAX+8];
+                add EAX, 16;
+                pmullw MM0, MM2;
+                pmullw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ * value);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceExpMulSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * 6))
+                {
+                    printf("[%d]: %d != %d * 6\n", i, c[i], a[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] = b[] * c[]
+ */
+
+T[] _arraySliceSliceMulSliceAssign_u(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMulSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceMulSliceAssign_t(T[] a, T[] c, T[] b)
+{
+    return _arraySliceSliceMulSliceAssign_s(a, c, b);
+}
+
+T[] _arraySliceSliceMulSliceAssign_s(T[] a, T[] c, T[] b)
+in
+{
+        assert(a.length == b.length && b.length == c.length);
+        assert(disjoint(a, b));
+        assert(disjoint(a, c));
+        assert(disjoint(b, c));
+}
+body
+{
+    //printf("_arraySliceSliceMulSliceAssign_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+    auto cptr = c.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 2515% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr | cast(uint) cptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2u:
+                    add ESI, 32;
+                    movdqu XMM0, [EAX];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [EAX+16];
+                    movdqu XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov EAX, bptr;
+                    mov ECX, cptr;
+
+                    align 4;
+                startsse2a:
+                    add ESI, 32;
+                    movdqa XMM0, [EAX];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [EAX+16];
+                    movdqa XMM3, [ECX+16];
+                    add EAX, 32;
+                    add ECX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, EAX;
+                    mov cptr, ECX;
+               }
+            }
+        }
+        else
+        // MMX version is 2515% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov EAX, bptr;
+                mov ECX, cptr;
+
+                align 4;
+            startmmx:
+                add ESI, 16;
+                movq MM0, [EAX];
+                movq MM2, [ECX];
+                movq MM1, [EAX+8];
+                movq MM3, [ECX+8];
+                add EAX, 16;
+                add ECX, 16;
+                pmullw MM0, MM2;
+                pmullw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, EAX;
+                mov cptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ = cast(T)(*bptr++ * *cptr++);
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulSliceAssign_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            c[] = a[] * b[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (c[i] != cast(T)(a[i] * b[i]))
+                {
+                    printf("[%d]: %d != %d * %d\n", i, c[i], a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= value
+ */
+
+T[] _arrayExpSliceMulass_u(T[] a, T value)
+{
+    return _arrayExpSliceMulass_s(a, value);
+}
+
+T[] _arrayExpSliceMulass_t(T[] a, T value)
+{
+    return _arrayExpSliceMulass_s(a, value);
+}
+
+T[] _arrayExpSliceMulass_s(T[] a, T value)
+{
+    //printf("_arrayExpSliceMulass_s(a.length = %d, value = %Lg)\n", a.length, cast(real)value);
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 2044% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            uint l = cast(ushort) value;
+            l |= l << 16;
+
+            if (((cast(uint) aptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM1, [ESI+16];
+                    add ESI, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM2;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    movd XMM2, l;
+                    pshufd XMM2, XMM2, 0;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM1, [ESI+16];
+                    add ESI, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM2;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                }
+            }
+        }
+        else
+        // MMX version is 2056% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            uint l = cast(ushort) value;
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                movd MM2, l;
+                pshufw MM2, MM2, 0;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM1, [ESI+8];
+                add ESI, 16;
+                pmullw MM0, MM2;
+                pmullw MM1, MM2;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= value;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arrayExpSliceMulass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = a[];
+            a[] *= 6;
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(b[i] * 6))
+                {
+                    printf("[%d]: %d != %d * 6\n", i, a[i], b[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
+
+
+/* ======================================================================== */
+
+/***********************
+ * Computes:
+ *      a[] *= b[]
+ */
+
+T[] _arraySliceSliceMulass_u(T[] a, T[] b)
+{
+    return _arraySliceSliceMulass_s(a, b);
+}
+
+T[] _arraySliceSliceMulass_t(T[] a, T[] b)
+{
+    return _arraySliceSliceMulass_s(a, b);
+}
+
+T[] _arraySliceSliceMulass_s(T[] a, T[] b)
+in
+{
+    assert (a.length == b.length);
+    assert (disjoint(a, b));
+}
+body
+{
+    //printf("_arraySliceSliceMulass_s()\n");
+    auto aptr = a.ptr;
+    auto aend = aptr + a.length;
+    auto bptr = b.ptr;
+
+    version (D_InlineAsm_X86)
+    {
+        // SSE2 aligned version is 2519% faster
+        if (sse2() && a.length >= 16)
+        {
+            auto n = aptr + (a.length & ~15);
+
+            if (((cast(uint) aptr | cast(uint) bptr) & 15) != 0)
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2u:
+                    movdqu XMM0, [ESI];
+                    movdqu XMM2, [ECX];
+                    movdqu XMM1, [ESI+16];
+                    movdqu XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM3;
+                    movdqu [ESI   -32], XMM0;
+                    movdqu [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2u;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+                }
+            }
+            else
+            {
+                asm
+                {
+                    mov ESI, aptr;
+                    mov EDI, n;
+                    mov ECX, bptr;
+
+                    align 4;
+                startsse2a:
+                    movdqa XMM0, [ESI];
+                    movdqa XMM2, [ECX];
+                    movdqa XMM1, [ESI+16];
+                    movdqa XMM3, [ECX+16];
+                    add ESI, 32;
+                    add ECX, 32;
+                    pmullw XMM0, XMM2;
+                    pmullw XMM1, XMM3;
+                    movdqa [ESI   -32], XMM0;
+                    movdqa [ESI+16-32], XMM1;
+                    cmp ESI, EDI;
+                    jb startsse2a;
+
+                    mov aptr, ESI;
+                    mov bptr, ECX;
+               }
+            }
+        }
+        else
+        // MMX version is 1712% faster
+        if (mmx() && a.length >= 8)
+        {
+            auto n = aptr + (a.length & ~7);
+
+            asm
+            {
+                mov ESI, aptr;
+                mov EDI, n;
+                mov ECX, bptr;
+
+                align 4;
+            startmmx:
+                movq MM0, [ESI];
+                movq MM2, [ECX];
+                movq MM1, [ESI+8];
+                movq MM3, [ECX+8];
+                add ESI, 16;
+                add ECX, 16;
+                pmullw MM0, MM2;
+                pmullw MM1, MM3;
+                movq [ESI  -16], MM0;
+                movq [ESI+8-16], MM1;
+                cmp ESI, EDI;
+                jb startmmx;
+
+                emms;
+                mov aptr, ESI;
+                mov bptr, ECX;
+            }
+        }
+    }
+
+    while (aptr < aend)
+        *aptr++ *= *bptr++;
+
+    return a;
+}
+
+unittest
+{
+    printf("_arraySliceSliceMulass_s unittest\n");
+
+    for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
+    {
+        version (log) printf("    cpuid %d\n", cpuid);
+
+        for (int j = 0; j < 2; j++)
+        {
+            const int dim = 67;
+            T[] a = new T[dim + j];     // aligned on 16 byte boundary
+            a = a[j .. dim + j];        // misalign for second iteration
+            T[] b = new T[dim + j];
+            b = b[j .. dim + j];
+            T[] c = new T[dim + j];
+            c = c[j .. dim + j];
+
+            for (int i = 0; i < dim; i++)
+            {   a[i] = cast(T)i;
+                b[i] = cast(T)(i + 7);
+                c[i] = cast(T)(i * 2);
+            }
+
+            b[] = a[];
+            a[] *= c[];
+
+            for (int i = 0; i < dim; i++)
+            {
+                if (a[i] != cast(T)(b[i] * c[i]))
+                {
+                    printf("[%d]: %d != %d * %d\n", i, a[i], b[i], c[i]);
+                    assert(0);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/cast_.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,169 @@
+/**
+ * Implementation of array assignment support routines.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.cast_;
+
+extern (C):
+
+/******************************************
+ * Given a pointer:
+ *      If it is an Object, return that Object.
+ *      If it is an interface, return the Object implementing the interface.
+ *      If it is null, return null.
+ *      Else, undefined crash
+ */
+
+Object _d_toObject(void* p)
+{   Object o;
+
+    if (p)
+    {
+        o = cast(Object)p;
+        ClassInfo oc = o.classinfo;
+        Interface *pi = **cast(Interface ***)p;
+
+        /* Interface.offset lines up with ClassInfo.name.ptr,
+         * so we rely on pointers never being less than 64K,
+         * and Objects never being greater.
+         */
+        if (pi.offset < 0x10000)
+        {
+            //printf("\tpi.offset = %d\n", pi.offset);
+            o = cast(Object)(p - pi.offset);
+        }
+    }
+    return o;
+}
+
+
+/*************************************
+ * Attempts to cast Object o to class c.
+ * Returns o if successful, null if not.
+ */
+
+Object _d_interface_cast(void* p, ClassInfo c)
+{   Object o;
+
+    //printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
+    if (p)
+    {
+        Interface *pi = **cast(Interface ***)p;
+
+        //printf("\tpi.offset = %d\n", pi.offset);
+        o = cast(Object)(p - pi.offset);
+        return _d_dynamic_cast(o, c);
+    }
+    return o;
+}
+
+Object _d_dynamic_cast(Object o, ClassInfo c)
+{   ClassInfo oc;
+    size_t offset = 0;
+
+    //printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
+
+    if (o)
+    {
+        oc = o.classinfo;
+        if (_d_isbaseof2(oc, c, offset))
+        {
+            //printf("\toffset = %d\n", offset);
+            o = cast(Object)(cast(void*)o + offset);
+        }
+        else
+            o = null;
+    }
+    //printf("\tresult = %p\n", o);
+    return o;
+}
+
+int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout size_t offset)
+{   int i;
+
+    if (oc is c)
+        return 1;
+    do
+    {
+        if (oc.base is c)
+            return 1;
+        for (i = 0; i < oc.interfaces.length; i++)
+        {
+            ClassInfo ic;
+
+            ic = oc.interfaces[i].classinfo;
+            if (ic is c)
+            {   offset = oc.interfaces[i].offset;
+                return 1;
+            }
+        }
+        for (i = 0; i < oc.interfaces.length; i++)
+        {
+            ClassInfo ic;
+
+            ic = oc.interfaces[i].classinfo;
+            if (_d_isbaseof2(ic, c, offset))
+            {   offset = oc.interfaces[i].offset;
+                return 1;
+            }
+        }
+        oc = oc.base;
+    } while (oc);
+    return 0;
+}
+
+int _d_isbaseof(ClassInfo oc, ClassInfo c)
+{   int i;
+
+    if (oc is c)
+        return 1;
+    do
+    {
+        if (oc.base is c)
+            return 1;
+        for (i = 0; i < oc.interfaces.length; i++)
+        {
+            ClassInfo ic;
+
+            ic = oc.interfaces[i].classinfo;
+            if (ic is c || _d_isbaseof(ic, c))
+                return 1;
+        }
+        oc = oc.base;
+    } while (oc);
+    return 0;
+}
+
+/*********************************
+ * Find the vtbl[] associated with Interface ic.
+ */
+
+void *_d_interface_vtbl(ClassInfo ic, Object o)
+{   int i;
+    ClassInfo oc;
+
+    //printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
+
+    assert(o);
+
+    oc = o.classinfo;
+    for (i = 0; i < oc.interfaces.length; i++)
+    {
+        ClassInfo oic;
+
+        oic = oc.interfaces[i].classinfo;
+        if (oic is ic)
+        {
+            return cast(void *)oc.interfaces[i].vtbl;
+        }
+    }
+    assert(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/cmath2.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,218 @@
+/**
+ * Runtime support for complex arithmetic code generation (for Posix).
+ *
+ * Copyright: Copyright Digital Mars 2001 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2001 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.cmath2;
+
+private import core.stdc.math;
+
+extern (C):
+
+/****************************
+ * Multiply two complex floating point numbers, x and y.
+ * Input:
+ *      x.re    ST3
+ *      x.im    ST2
+ *      y.re    ST1
+ *      y.im    ST0
+ * Output:
+ *      ST1     real part
+ *      ST0     imaginary part
+ */
+
+void _Cmul()
+{
+    // p.re = x.re * y.re - x.im * y.im;
+    // p.im = x.im * y.re + x.re * y.im;
+    asm
+    {   naked                   ;
+        fld     ST(1)           ; // x.re
+        fmul    ST,ST(4)        ; // ST0 = x.re * y.re
+
+        fld     ST(1)           ; // y.im
+        fmul    ST,ST(4)        ; // ST0 = x.im * y.im
+
+        fsubp   ST(1),ST        ; // ST0 = x.re * y.re - x.im * y.im
+
+        fld     ST(3)           ; // x.im
+        fmul    ST,ST(3)        ; // ST0 = x.im * y.re
+
+        fld     ST(5)           ; // x.re
+        fmul    ST,ST(3)        ; // ST0 = x.re * y.im
+
+        faddp   ST(1),ST        ; // ST0 = x.im * y.re + x.re * y.im
+
+        fxch    ST(4),ST        ;
+        fstp    ST(0)           ;
+        fxch    ST(4),ST        ;
+        fstp    ST(0)           ;
+        fstp    ST(0)           ;
+        fstp    ST(0)           ;
+
+        ret                     ;
+    }
+/+
+    if (isnan(x) && isnan(y))
+    {
+        // Recover infinities that computed as NaN+ iNaN ...
+        int recalc = 0;
+        if ( isinf( a) || isinf( b) )
+        {   // z is infinite
+            // "Box" the infinity and change NaNs in the other factor to 0
+            a = copysignl( isinf( a) ? 1.0 : 0.0, a);
+            b = copysignl( isinf( b) ? 1.0 : 0.0, b);
+            if (isnan( c)) c = copysignl( 0.0, c);
+            if (isnan( d)) d = copysignl( 0.0, d);
+            recalc = 1;
+        }
+        if (isinf(c) || isinf(d))
+        {   // w is infinite
+            // "Box" the infinity and change NaNs in the other factor to 0
+            c = copysignl( isinf( c) ? 1.0 : 0.0, c);
+            d = copysignl( isinf( d) ? 1.0 : 0.0, d);
+            if (isnan( a)) a = copysignl( 0.0, a);
+            if (isnan( b)) b = copysignl( 0.0, b);
+            recalc = 1;
+        }
+        if (!recalc && (isinf(ac) || isinf(bd) ||
+            isinf(ad) || isinf(bc)))
+        {
+            // Recover infinities from overflow by changing NaNs to 0 ...
+            if (isnan( a)) a = copysignl( 0.0, a);
+            if (isnan( b)) b = copysignl( 0.0, b);
+            if (isnan( c)) c = copysignl( 0.0, c);
+            if (isnan( d)) d = copysignl( 0.0, d);
+            recalc = 1;
+        }
+        if (recalc)
+        {
+            x = INFINITY * (a * c - b * d);
+            y = INFINITY * (a * d + b * c);
+        }
+    }
++/
+}
+
+/****************************
+ * Divide two complex floating point numbers, x / y.
+ * Input:
+ *      x.re    ST3
+ *      x.im    ST2
+ *      y.re    ST1
+ *      y.im    ST0
+ * Output:
+ *      ST1     real part
+ *      ST0     imaginary part
+ */
+
+void _Cdiv()
+{
+    real x_re, x_im;
+    real y_re, y_im;
+    real q_re, q_im;
+    real r;
+    real den;
+
+    asm
+    {
+        fstp    y_im    ;
+        fstp    y_re    ;
+        fstp    x_im    ;
+        fstp    x_re    ;
+    }
+
+    if (fabs(y_re) < fabs(y_im))
+    {
+        r = y_re / y_im;
+        den = y_im + r * y_re;
+        q_re = (x_re * r + x_im) / den;
+        q_im = (x_im * r - x_re) / den;
+    }
+    else
+    {
+        r = y_im / y_re;
+        den = y_re + r * y_im;
+        q_re = (x_re + r * x_im) / den;
+        q_im = (x_im - r * x_re) / den;
+    }
+//printf("q.re = %g, q.im = %g\n", (double)q_re, (double)q_im);
+/+
+    if (isnan(q_re) && isnan(q_im))
+    {
+        real denom = y_re * y_re + y_im * y_im;
+
+        // non-zero / zero
+        if (denom == 0.0 && (!isnan(x_re) || !isnan(x_im)))
+        {
+            q_re = copysignl(INFINITY, y_re) * x_re;
+            q_im = copysignl(INFINITY, y_re) * x_im;
+        }
+        // infinite / finite
+        else if ((isinf(x_re) || isinf(x_im)) && isfinite(y_re) && isfinite(y_im))
+        {
+            x_re = copysignl(isinf(x_re) ? 1.0 : 0.0, x_re);
+            x_im = copysignl(isinf(x_im) ? 1.0 : 0.0, x_im);
+            q_re = INFINITY * (x_re * y_re + x_im * y_im);
+            q_im = INFINITY * (x_im * y_re - x_re * y_im);
+        }
+        // finite / infinite
+        else if (isinf(logbw) && isfinite(x_re) && isfinite(x_im))
+        {
+            y_re = copysignl(isinf(y_re) ? 1.0 : 0.0, y_re);
+            y_im = copysignl(isinf(y_im) ? 1.0 : 0.0, y_im);
+            q_re = 0.0 * (x_re * y_re + x_im * y_im);
+            q_im = 0.0 * (x_im * y_re - x_re * y_im);
+        }
+    }
+    return q_re + q_im * 1.0i;
++/
+    asm
+    {
+        fld     q_re;
+        fld     q_im;
+    }
+}
+
+/****************************
+ * Compare two complex floating point numbers, x and y.
+ * Input:
+ *      x.re    ST3
+ *      x.im    ST2
+ *      y.re    ST1
+ *      y.im    ST0
+ * Output:
+ *      8087 stack is cleared
+ *      flags set
+ */
+
+void _Ccmp()
+{
+    asm
+    {   naked                   ;
+        fucomp  ST(2)           ; // compare x.im and y.im
+        fstsw   AX              ;
+        sahf                    ;
+        jne     L1              ;
+        jp      L1              ; // jmp if NAN
+        fucomp  ST(2)           ; // compare x.re and y.re
+        fstsw   AX              ;
+        sahf                    ;
+        fstp    ST(0)           ; // pop
+        fstp    ST(0)           ; // pop
+        ret                     ;
+
+      L1:
+        fstp    ST(0)           ; // pop
+        fstp    ST(0)           ; // pop
+        fstp    ST(0)           ; // pop
+        ret                     ;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/compiler.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,42 @@
+/**
+ * Compiler information and associated routines.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.compiler;
+
+// Identify the compiler used and its various features.
+
+const
+{
+    // Vendor specific string naming the compiler
+    char[] name = "Digital Mars D";
+
+    // Master list of D compiler vendors
+    enum Vendor
+    {
+        DigitalMars = 1
+    }
+
+    // Which vendor we are
+    Vendor vendor = Vendor.DigitalMars;
+
+
+    // The vendor specific version number, as in
+    // version_major.version_minor
+    uint version_major = 0;
+    uint version_minor = 0;
+
+
+    // The version of the D Programming Language Specification
+    // Supported by the compiler
+    uint D_major = 0;
+    uint D_minor = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/complex.c	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,112 @@
+/**
+ * Implementation of complex number support routines.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#include <math.h>
+
+typedef struct Complex
+{
+    long double re;
+    long double im;
+} Complex;
+
+Complex _complex_div(Complex x, Complex y)
+{
+    Complex q;
+    long double r;
+    long double den;
+
+    if (fabs(y.re) < fabs(y.im))
+    {
+        r = y.re / y.im;
+        den = y.im + r * y.re;
+        q.re = (x.re * r + x.im) / den;
+        q.im = (x.im * r - x.re) / den;
+    }
+    else
+    {
+        r = y.im / y.re;
+        den = y.re + r * y.im;
+        q.re = (x.re + r * x.im) / den;
+        q.im = (x.im - r * x.re) / den;
+    }
+    return q;
+}
+
+Complex _complex_mul(Complex x, Complex y)
+{
+    Complex p;
+
+    p.re = x.re * y.re - x.im * y.im;
+    p.im = x.im * y.re + x.re * y.im;
+    return p;
+}
+
+long double _complex_abs(Complex z)
+{
+    long double x,y,ans,temp;
+
+    x = fabs(z.re);
+    y = fabs(z.im);
+    if (x == 0)
+        ans = y;
+    else if (y == 0)
+        ans = x;
+    else if (x > y)
+    {
+        temp = y / x;
+        ans = x * sqrt(1 + temp * temp);
+    }
+    else
+    {
+        temp = x / y;
+        ans = y * sqrt(1 + temp * temp);
+    }
+    return ans;
+}
+
+Complex _complex_sqrt(Complex z)
+{
+    Complex c;
+    long double x,y,w,r;
+
+    if (z.re == 0 && z.im == 0)
+    {
+        c.re = 0;
+        c.im = 0;
+    }
+    else
+    {
+        x = fabs(z.re);
+        y = fabs(z.im);
+        if (x >= y)
+        {
+            r = y / x;
+            w = sqrt(x) * sqrt(0.5 * (1 + sqrt(1 + r * r)));
+        }
+        else
+        {
+            r = x / y;
+            w = sqrt(y) * sqrt(0.5 * (r + sqrt(1 + r * r)));
+        }
+        if (z.re >= 0)
+        {
+            c.re = w;
+            c.im = z.im / (w + w);
+        }
+        else
+        {
+            c.im = (z.im >= 0) ? w : -w;
+            c.re = z.im / (c.im + c.im);
+        }
+    }
+    return c;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/cover.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,463 @@
+/**
+ * Implementation of code coverage analyzer.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.cover;
+
+private
+{
+    version( Windows )
+        import core.sys.windows.windows;
+    else version( Posix )
+    {
+        import core.sys.posix.fcntl;
+        import core.sys.posix.unistd;
+    }
+    import core.bitop;
+    import core.stdc.stdio;
+    import rt.util.utf;
+
+    struct BitArray
+    {
+        size_t  len;
+        uint*   ptr;
+
+        bool opIndex( size_t i )
+        in
+        {
+            assert( i < len );
+        }
+        body
+        {
+            return cast(bool) bt( ptr, i );
+        }
+    }
+
+    struct Cover
+    {
+        string      filename;
+        BitArray    valid;
+        uint[]      data;
+    }
+
+    __gshared
+    {
+	Cover[] gdata;
+	string  srcpath;
+	string  dstpath;
+	bool    merge;
+    }
+}
+
+
+/**
+ * Set path to where source files are located.
+ *
+ * Params:
+ *  pathname = The new path name.
+ */
+extern (C) void dmd_coverSourcePath( string pathname )
+{
+    srcpath = pathname;
+}
+
+
+/**
+ * Set path to where listing files are to be written.
+ *
+ * Params:
+ *  pathname = The new path name.
+ */
+extern (C) void dmd_coverDestPath( string pathname )
+{
+    dstpath = pathname;
+}
+
+
+/**
+ * Set merge mode.
+ *
+ * Params:
+ *      flag = true means new data is summed with existing data in the listing
+ *         file; false means a new listing file is always created.
+ */
+extern (C) void dmd_coverSetMerge( bool flag )
+{
+    merge = flag;
+}
+
+
+/**
+ * The coverage callback.
+ *
+ * Params:
+ *  filename = The name of the coverage file.
+ *  valid    = ???
+ *  data     = ???
+ */
+extern (C) void _d_cover_register( string filename, BitArray valid, uint[] data )
+{
+    Cover c;
+
+    c.filename  = filename;
+    c.valid     = valid;
+    c.data      = data;
+    gdata      ~= c;
+}
+
+
+static ~this()
+{
+    const NUMLINES = 16384 - 1;
+    const NUMCHARS = 16384 * 16 - 1;
+
+    char[]      srcbuf      = new char[NUMCHARS];
+    char[][]    srclines    = new char[][NUMLINES];
+    char[]      lstbuf      = new char[NUMCHARS];
+    char[][]    lstlines    = new char[][NUMLINES];
+
+    foreach( Cover c; gdata )
+    {
+        if( !readFile( appendFN( srcpath, c.filename ), srcbuf ) )
+            continue;
+        splitLines( srcbuf, srclines );
+
+        if( merge )
+        {
+            if( !readFile( addExt( baseName( c.filename ), "lst" ), lstbuf ) )
+                break;
+            splitLines( lstbuf, lstlines );
+
+            for( size_t i = 0; i < lstlines.length; ++i )
+            {
+                if( i >= c.data.length )
+                    break;
+
+                int count = 0;
+
+                foreach( char c2; lstlines[i] )
+                {
+                    switch( c2 )
+                    {
+                    case ' ':
+                        continue;
+                    case '0': case '1': case '2': case '3': case '4':
+                    case '5': case '6': case '7': case '8': case '9':
+                        count = count * 10 + c2 - '0';
+                        continue;
+                    default:
+                        break;
+                    }
+                }
+                c.data[i] += count;
+            }
+        }
+
+        FILE* flst = fopen( (addExt( baseName( c.filename ), "lst\0" )).ptr, "wb" );
+
+        if( !flst )
+            continue; //throw new Exception( "Error opening file for write: " ~ lstfn );
+
+        uint nno;
+        uint nyes;
+
+        for( int i = 0; i < c.data.length; i++ )
+        {
+            if( i < srclines.length )
+            {
+                uint    n    = c.data[i];
+                char[]  line = srclines[i];
+
+                line = expandTabs( line );
+
+                if( n == 0 )
+                {
+                    if( c.valid[i] )
+                    {
+                        nno++;
+                        fprintf( flst, "0000000|%.*s\n", line );
+                    }
+                    else
+                    {
+                        fprintf( flst, "       |%.*s\n", line );
+                    }
+                }
+                else
+                {
+                    nyes++;
+                    fprintf( flst, "%7u|%.*s\n", n, line );
+                }
+            }
+        }
+        if( nyes + nno ) // no divide by 0 bugs
+        {
+            fprintf( flst, "%.*s is %d%% covered\n", c.filename, ( nyes * 100 ) / ( nyes + nno ) );
+        }
+        fclose( flst );
+    }
+}
+
+
+string appendFN( string path, string name )
+{
+    version( Windows )
+        const char sep = '\\';
+    else
+        const char sep = '/';
+
+    auto dest = path;
+
+    if( dest && dest[$ - 1] != sep )
+        dest ~= sep;
+    dest ~= name;
+    return dest;
+}
+
+
+string baseName( string name, string ext = null )
+{
+    auto i = name.length;
+    for( ; i > 0; --i )
+    {
+        version( Windows )
+        {
+            if( name[i - 1] == ':' || name[i - 1] == '\\' )
+                break;
+        }
+        else version( Posix )
+        {
+            if( name[i - 1] == '/' )
+                break;
+        }
+    }
+    return chomp( name[i .. $], ext ? ext : "" );
+}
+
+
+string getExt( string name )
+{
+    auto i = name.length;
+
+    while( i > 0 )
+    {
+        if( name[i - 1] == '.' )
+            return name[i .. $];
+        --i;
+        version( Windows )
+        {
+            if( name[i] == ':' || name[i] == '\\' )
+                break;
+        }
+        else version( Posix )
+        {
+            if( name[i] == '/' )
+                break;
+        }
+    }
+    return null;
+}
+
+
+string addExt( string name, string ext )
+{
+    auto  existing = getExt( name );
+
+    if( existing.length == 0 )
+    {
+        if( name.length && name[$ - 1] == '.' )
+            name ~= ext;
+        else
+            name = name ~ "." ~ ext;
+    }
+    else
+    {
+        name = name[0 .. $ - existing.length] ~ ext;
+    }
+    return name;
+}
+
+
+string chomp( string str, string delim = null )
+{
+    if( delim is null )
+    {
+        auto len = str.length;
+
+        if( len )
+        {
+            auto c = str[len - 1];
+
+            if( c == '\r' )
+                --len;
+            else if( c == '\n' && str[--len - 1] == '\r' )
+                --len;
+        }
+        return str[0 .. len];
+    }
+    else if( str.length >= delim.length )
+    {
+        if( str[$ - delim.length .. $] == delim )
+            return str[0 .. $ - delim.length];
+    }
+    return str;
+}
+
+
+bool readFile( string name, inout char[] buf )
+{
+    version( Windows )
+    {
+        auto    wnamez  = toUTF16z( name );
+        HANDLE  file    = CreateFileW( wnamez,
+                                       GENERIC_READ,
+                                       FILE_SHARE_READ,
+                                       null,
+                                       OPEN_EXISTING,
+                                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+                                       cast(HANDLE) null );
+
+        delete wnamez;
+        if( file == INVALID_HANDLE_VALUE )
+            return false;
+        scope( exit ) CloseHandle( file );
+
+        DWORD   num = 0;
+        DWORD   pos = 0;
+
+        buf.length = 4096;
+        while( true )
+        {
+            if( !ReadFile( file, &buf[pos], cast(DWORD)( buf.length - pos ), &num, null ) )
+                return false;
+            if( !num )
+                break;
+            pos += num;
+            buf.length = pos * 2;
+        }
+        buf.length = pos;
+        return true;
+    }
+    else version( Posix )
+    {
+        char[]  namez = new char[name.length + 1];
+                        namez[0 .. name.length] = name;
+                        namez[$ - 1] = 0;
+        int     file = open( namez.ptr, O_RDONLY );
+
+        delete namez;
+        if( file == -1 )
+            return false;
+        scope( exit ) close( file );
+
+        int     num = 0;
+        uint    pos = 0;
+
+        buf.length = 4096;
+        while( true )
+        {
+            num = read( file, &buf[pos], cast(uint)( buf.length - pos ) );
+            if( num == -1 )
+                return false;
+            if( !num )
+                break;
+            pos += num;
+            buf.length = pos * 2;
+        }
+        buf.length = pos;
+        return true;
+    }
+}
+
+
+void splitLines( char[] buf, inout char[][] lines )
+{
+    size_t  beg = 0,
+            pos = 0;
+
+    lines.length = 0;
+    for( ; pos < buf.length; ++pos )
+    {
+        char c = buf[pos];
+
+        switch( buf[pos] )
+        {
+        case '\r':
+        case '\n':
+            lines ~= buf[beg .. pos];
+            beg = pos + 1;
+            if( buf[pos] == '\r' && pos < buf.length - 1 && buf[pos + 1] == '\n' )
+                ++pos, ++beg;
+        default:
+            continue;
+        }
+    }
+    if( beg != pos )
+    {
+        lines ~= buf[beg .. pos];
+    }
+}
+
+
+char[] expandTabs( char[] str, int tabsize = 8 )
+{
+    const dchar LS = '\u2028'; // UTF line separator
+    const dchar PS = '\u2029'; // UTF paragraph separator
+
+    bool changes = false;
+    char[] result = str;
+    int column;
+    int nspaces;
+
+    foreach( size_t i, dchar c; str )
+    {
+        switch( c )
+        {
+            case '\t':
+                nspaces = tabsize - (column % tabsize);
+                if( !changes )
+                {
+                    changes = true;
+                    result = null;
+                    result.length = str.length + nspaces - 1;
+                    result.length = i + nspaces;
+                    result[0 .. i] = str[0 .. i];
+                    result[i .. i + nspaces] = ' ';
+                }
+                else
+                {   int j = result.length;
+                    result.length = j + nspaces;
+                    result[j .. j + nspaces] = ' ';
+                }
+                column += nspaces;
+                break;
+
+            case '\r':
+            case '\n':
+            case PS:
+            case LS:
+                column = 0;
+                goto L1;
+
+            default:
+                column++;
+            L1:
+                if (changes)
+                {
+                    if (c <= 0x7F)
+                        result ~= c;
+                    else
+                        encode(result, c);
+                }
+                break;
+        }
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/critical.c	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,173 @@
+/**
+ * Implementation of support routines for synchronized blocks.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+/* ================================= Win32 ============================ */
+
+#if _WIN32
+
+#include <windows.h>
+
+/******************************************
+ * Enter/exit critical section.
+ */
+
+/* We don't initialize critical sections unless we actually need them.
+ * So keep a linked list of the ones we do use, and in the static destructor
+ * code, walk the list and release them.
+ */
+
+typedef struct D_CRITICAL_SECTION
+{
+    struct D_CRITICAL_SECTION *next;
+    CRITICAL_SECTION cs;
+} D_CRITICAL_SECTION;
+
+static D_CRITICAL_SECTION *dcs_list;
+static D_CRITICAL_SECTION critical_section;
+static volatile int inited;
+
+void _d_criticalenter(D_CRITICAL_SECTION *dcs)
+{
+    if (!dcs->next)
+    {
+        EnterCriticalSection(&critical_section.cs);
+        if (!dcs->next) // if, in the meantime, another thread didn't set it
+        {
+            dcs->next = dcs_list;
+            dcs_list = dcs;
+            InitializeCriticalSection(&dcs->cs);
+        }
+        LeaveCriticalSection(&critical_section.cs);
+    }
+    EnterCriticalSection(&dcs->cs);
+}
+
+void _d_criticalexit(D_CRITICAL_SECTION *dcs)
+{
+    LeaveCriticalSection(&dcs->cs);
+}
+
+void _STI_critical_init()
+{
+    if (!inited)
+    {   InitializeCriticalSection(&critical_section.cs);
+        dcs_list = &critical_section;
+        inited = 1;
+    }
+}
+
+void _STD_critical_term()
+{
+    if (inited)
+    {   inited = 0;
+        while (dcs_list)
+        {
+            DeleteCriticalSection(&dcs_list->cs);
+            dcs_list = dcs_list->next;
+        }
+    }
+}
+
+#endif
+
+/* ================================= linux ============================ */
+
+#if linux || __APPLE__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+// PTHREAD_MUTEX_RECURSIVE is the "standard" symbol,
+// while the _NP version is specific to Linux
+#ifndef PTHREAD_MUTEX_RECURSIVE
+#    define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
+#endif
+
+/******************************************
+ * Enter/exit critical section.
+ */
+
+/* We don't initialize critical sections unless we actually need them.
+ * So keep a linked list of the ones we do use, and in the static destructor
+ * code, walk the list and release them.
+ */
+
+typedef struct D_CRITICAL_SECTION
+{
+    struct D_CRITICAL_SECTION *next;
+    pthread_mutex_t cs;
+} D_CRITICAL_SECTION;
+
+static D_CRITICAL_SECTION *dcs_list;
+static D_CRITICAL_SECTION critical_section;
+static pthread_mutexattr_t _criticals_attr;
+
+void _STI_critical_init(void);
+void _STD_critical_term(void);
+
+void _d_criticalenter(D_CRITICAL_SECTION *dcs)
+{
+    if (!dcs_list)
+    {   _STI_critical_init();
+        atexit(_STD_critical_term);
+    }
+    //printf("_d_criticalenter(dcs = x%x)\n", dcs);
+    if (!dcs->next)
+    {
+        pthread_mutex_lock(&critical_section.cs);
+        if (!dcs->next) // if, in the meantime, another thread didn't set it
+        {
+            dcs->next = dcs_list;
+            dcs_list = dcs;
+            pthread_mutex_init(&dcs->cs, &_criticals_attr);
+        }
+        pthread_mutex_unlock(&critical_section.cs);
+    }
+    pthread_mutex_lock(&dcs->cs);
+}
+
+void _d_criticalexit(D_CRITICAL_SECTION *dcs)
+{
+    //printf("_d_criticalexit(dcs = x%x)\n", dcs);
+    pthread_mutex_unlock(&dcs->cs);
+}
+
+void _STI_critical_init()
+{
+    if (!dcs_list)
+    {   //printf("_STI_critical_init()\n");
+        pthread_mutexattr_init(&_criticals_attr);
+        pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE);
+
+        // The global critical section doesn't need to be recursive
+        pthread_mutex_init(&critical_section.cs, 0);
+        dcs_list = &critical_section;
+    }
+}
+
+void _STD_critical_term()
+{
+    if (dcs_list)
+    {   //printf("_STI_critical_term()\n");
+        while (dcs_list)
+        {
+            //printf("\tlooping... %x\n", dcs_list);
+            pthread_mutex_destroy(&dcs_list->cs);
+            dcs_list = dcs_list->next;
+        }
+    }
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/deh.c	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,724 @@
+/**
+ * Implementation of exception handling support routines for Windows.
+ *
+ * Copyright: Copyright Digital Mars 1999 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 1999 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#include        <stdio.h>
+#include        <string.h>
+#include        <assert.h>
+#include        <stdlib.h>
+
+/* ======================== Win32 =============================== */
+
+#if _WIN32
+
+#include        <excpt.h>
+#include        <windows.h>
+
+//#include      "\sc\src\include\ehsup.h"
+
+/*** From Digital Mars C runtime library ***/
+EXCEPTION_DISPOSITION __cdecl _local_except_handler (EXCEPTION_RECORD *ExceptionRecord,
+    void* EstablisherFrame,
+        void *ContextRecord,
+        void *DispatcherContext
+        );
+void __cdecl _global_unwind(void *frame,EXCEPTION_RECORD *eRecord);
+#define EXCEPTION_UNWIND  6  // Flag to indicate if the system is unwinding
+
+extern DWORD _except_list;
+/*** ***/
+
+#include        "mars.h"
+
+extern ClassInfo D6object9Throwable7__ClassZ;
+#define _Class_9Throwable D6object9Throwable7__ClassZ;
+
+extern ClassInfo D6object5Error7__ClassZ;
+#define _Class_5Error D6object5Error7__ClassZ
+
+typedef int (__pascal *fp_t)();   // function pointer in ambient memory model
+
+// The layout of DEstablisherFrame is the same for C++
+
+struct DEstablisherFrame
+{
+    void *prev;                 // pointer to previous exception list
+    void *handler;              // pointer to routine for exception handler
+    DWORD table_index;          // current index into handler_info[]
+    DWORD ebp;                  // this is EBP of routine
+};
+
+struct DHandlerInfo
+{
+    int prev_index;             // previous table index
+    unsigned cioffset;          // offset to DCatchInfo data from start of table (!=0 if try-catch)
+    void *finally_code;         // pointer to finally code to execute
+                                // (!=0 if try-finally)
+};
+
+// Address of DHandlerTable is passed in EAX to _d_framehandler()
+
+struct DHandlerTable
+{
+    void *fptr;                 // pointer to start of function
+    unsigned espoffset;         // offset of ESP from EBP
+    unsigned retoffset;         // offset from start of function to return code
+    struct DHandlerInfo handler_info[1];
+};
+
+struct DCatchBlock
+{
+    ClassInfo *type;            // catch type
+    unsigned bpoffset;          // EBP offset of catch var
+    void *code;                 // catch handler code
+};
+
+// Create one of these for each try-catch
+struct DCatchInfo
+{
+    unsigned ncatches;                  // number of catch blocks
+    struct DCatchBlock catch_block[1];  // data for each catch block
+};
+
+// Macro to make our own exception code
+#define MAKE_EXCEPTION_CODE(severity, facility, exception)      \
+        (((severity) << 30) | (1 << 29) | (0 << 28) | ((facility) << 16) | (exception))
+
+#define STATUS_DIGITAL_MARS_D_EXCEPTION         MAKE_EXCEPTION_CODE(3,'D',1)
+
+Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record);
+void __cdecl _d_local_unwind(struct DHandlerTable *handler_table, struct DEstablisherFrame *frame, int stop_index);
+
+
+/***********************************
+ * The frame handler, this is called for each frame that has been registered
+ * in the OS except_list.
+ * Input:
+ *      EAX     the handler table for the frame
+ */
+
+EXCEPTION_DISPOSITION _d_framehandler(
+            EXCEPTION_RECORD *exception_record,
+            struct DEstablisherFrame *frame,
+            CONTEXT context,
+            void *dispatcher_context)
+{
+    struct DHandlerTable *handler_table;
+
+    __asm { mov handler_table,EAX }
+
+    if (exception_record->ExceptionFlags & EXCEPTION_UNWIND)
+    {
+         // Call all the finally blocks in this frame
+         _d_local_unwind(handler_table, frame, -1);
+    }
+    else
+    {
+        // Jump to catch block if matching one is found
+
+        int ndx,prev_ndx,i;
+        struct DHandlerInfo *phi;
+        struct DCatchInfo *pci;
+        struct DCatchBlock *pcb;
+        unsigned ncatches;              // number of catches in the current handler
+        Object *pti;
+        ClassInfo *ci;
+
+        ci = NULL;                      // only compute it if we need it
+
+        // walk through handler table, checking each handler
+        // with an index smaller than the current table_index
+        for (ndx = frame->table_index; ndx != -1; ndx = prev_ndx)
+        {
+            phi = &handler_table->handler_info[ndx];
+            prev_ndx = phi->prev_index;
+            if (phi->cioffset)
+            {
+                // this is a catch handler (no finally)
+                pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset);
+                ncatches = pci->ncatches;
+                for (i = 0; i < ncatches; i++)
+                {
+                    pcb = &pci->catch_block[i];
+
+                    if (!ci)
+                    {
+                        // This code must match the translation code
+                        if (exception_record->ExceptionCode == STATUS_DIGITAL_MARS_D_EXCEPTION)
+                        {
+                            //printf("ei[0] = %p\n", exception_record->ExceptionInformation[0]);
+                            ci = **(ClassInfo ***)(exception_record->ExceptionInformation[0]);
+                        }
+                        else
+                            ci = &_Class_9Throwable;
+                    }
+
+                    if (_d_isbaseof(ci, pcb->type))
+                    {
+                        // Matched the catch type, so we've found the handler.
+                        int regebp;
+
+                        pti = _d_translate_se_to_d_exception(exception_record);
+
+                        // Initialize catch variable
+                        regebp = (int)&frame->ebp;              // EBP for this frame
+                        *(void **)(regebp + (pcb->bpoffset)) = pti;
+
+                        // Have system call all finally blocks in intervening frames
+                        _global_unwind(frame, exception_record);
+
+                        // Call all the finally blocks skipped in this frame
+                        _d_local_unwind(handler_table, frame, ndx);
+
+                        frame->table_index = prev_ndx;  // we are out of this handler
+
+                        // Jump to catch block. Does not return.
+                        {
+                            unsigned catch_esp;
+                            fp_t catch_addr;
+
+                            catch_addr = (fp_t)(pcb->code);
+                            catch_esp = regebp - handler_table->espoffset - sizeof(fp_t);
+                            _asm
+                            {
+                                mov     EAX,catch_esp
+                                mov     ECX,catch_addr
+                                mov     [EAX],ECX
+                                mov     EBP,regebp
+                                mov     ESP,EAX         // reset stack
+                                ret                     // jump to catch block
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return ExceptionContinueSearch;
+}
+
+/***********************************
+ * Exception filter for use in __try..__except block
+ * surrounding call to Dmain()
+ */
+
+int _d_exception_filter(struct _EXCEPTION_POINTERS *eptrs,
+                        int retval,
+                        Object **exception_object)
+{
+    *exception_object = _d_translate_se_to_d_exception(eptrs->ExceptionRecord);
+    return retval;
+}
+
+/***********************************
+ * Throw a D object.
+ */
+
+void __stdcall _d_throw(Object *h)
+{
+    //printf("_d_throw(h = %p, &h = %p)\n", h, &h);
+    //printf("\tvptr = %p\n", *(void **)h);
+    RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION,
+                   EXCEPTION_NONCONTINUABLE,
+                   1, (DWORD *)&h);
+}
+
+/***********************************
+ * Create an exception object
+ */
+
+Object *_d_create_exception_object(ClassInfo *ci, char *msg)
+{
+    Throwable *exc;
+
+    exc = (Throwable *)_d_newclass(ci);
+    // BUG: what if _d_newclass() throws an out of memory exception?
+
+    if (msg)
+    {
+        exc->msglen = strlen(msg);
+        exc->msg = msg;
+    }
+    return (Object *)exc;
+}
+
+/***********************************
+ * Converts a Windows Structured Exception code to a D Exception Object.
+ */
+
+Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record)
+{
+    Object *pti;
+
+    switch (exception_record->ExceptionCode) {
+        case STATUS_DIGITAL_MARS_D_EXCEPTION:
+            // Generated D exception
+            pti = (Object *)(exception_record->ExceptionInformation[0]);
+            break;
+
+        case STATUS_INTEGER_DIVIDE_BY_ZERO:
+            pti = _d_create_exception_object(&_Class_5Error, "Integer Divide by Zero");
+            break;
+
+        case STATUS_FLOAT_DIVIDE_BY_ZERO:
+            pti = _d_create_exception_object(&_Class_5Error, "Float Divide by Zero");
+            break;
+
+        case STATUS_ACCESS_VIOLATION:
+            pti = _d_create_exception_object(&_Class_5Error, "Access Violation");
+            break;
+
+        case STATUS_STACK_OVERFLOW:
+            pti = _d_create_exception_object(&_Class_5Error, "Stack Overflow");
+            break;
+
+        case STATUS_DATATYPE_MISALIGNMENT:
+            pti = _d_create_exception_object(&_Class_5Error, "Datatype Misalignment");
+            break;
+
+        case STATUS_ARRAY_BOUNDS_EXCEEDED:
+            pti = _d_create_exception_object(&_Class_5Error, "Array Bounds Exceeded");
+            break;
+
+        case STATUS_FLOAT_INVALID_OPERATION:
+            pti = _d_create_exception_object(&_Class_5Error, "Invalid Floating Point Operation");
+            break;
+
+        case STATUS_FLOAT_DENORMAL_OPERAND:
+            pti = _d_create_exception_object(&_Class_5Error, "Floating Point Denormal Operand");
+            break;
+
+        case STATUS_FLOAT_INEXACT_RESULT:
+            pti = _d_create_exception_object(&_Class_5Error, "Floating Point Inexact Result");
+            break;
+
+        case STATUS_FLOAT_OVERFLOW:
+            pti = _d_create_exception_object(&_Class_5Error, "Floating Point Overflow");
+            break;
+
+        case STATUS_FLOAT_UNDERFLOW:
+            pti = _d_create_exception_object(&_Class_5Error, "Floating Point Underflow");
+            break;
+
+        case STATUS_FLOAT_STACK_CHECK:
+            pti = _d_create_exception_object(&_Class_5Error, "Floating Point Stack Check");
+            break;
+
+        case STATUS_PRIVILEGED_INSTRUCTION:
+            pti = _d_create_exception_object(&_Class_5Error, "Privileged Instruction");
+            break;
+
+        case STATUS_ILLEGAL_INSTRUCTION:
+            pti = _d_create_exception_object(&_Class_5Error, "Illegal Instruction");
+            break;
+
+        case STATUS_BREAKPOINT:
+            pti = _d_create_exception_object(&_Class_5Error, "Breakpoint");
+            break;
+
+        case STATUS_IN_PAGE_ERROR:
+            pti = _d_create_exception_object(&_Class_5Error, "Win32 In Page Exception");
+            break;
+/*
+        case STATUS_INTEGER_OVERFLOW: // not supported on any x86 processor
+        case STATUS_INVALID_DISPOSITION:
+        case STATUS_NONCONTINUABLE_EXCEPTION:
+        case STATUS_SINGLE_STEP:
+		case DBG_CONTROL_C: // only when a debugger is attached
+        // In DMC, but not in Microsoft docs
+        case STATUS_GUARD_PAGE_VIOLATION:
+        case STATUS_INVALID_HANDLE:
+*/
+        // convert all other exception codes into a Win32Exception
+        default:
+            pti = _d_create_exception_object(&_Class_5Error, "Win32 Exception");
+            break;
+    }
+
+    return pti;
+}
+
+/**************************************
+ * Call finally blocks in the current stack frame until stop_index.
+ * This is roughly equivalent to _local_unwind() for C in \src\win32\ehsup.c
+ */
+
+void __cdecl _d_local_unwind(struct DHandlerTable *handler_table,
+        struct DEstablisherFrame *frame, int stop_index)
+{
+    struct DHandlerInfo *phi;
+    struct DCatchInfo *pci;
+    int i;
+
+    // Set up a special exception handler to catch double-fault exceptions.
+    __asm
+    {
+        push    dword ptr -1
+        push    dword ptr 0
+        push    offset _local_except_handler    // defined in src\win32\ehsup.c
+        push    dword ptr fs:_except_list
+        mov     FS:_except_list,ESP
+    }
+
+    for (i = frame->table_index; i != -1 && i != stop_index; i = phi->prev_index)
+    {
+        phi = &handler_table->handler_info[i];
+        if (phi->finally_code)
+        {
+            // Note that it is unnecessary to adjust the ESP, as the finally block
+            // accesses all items on the stack as relative to EBP.
+
+            DWORD *catch_ebp = &frame->ebp;
+            void *blockaddr = phi->finally_code;
+
+            _asm
+            {
+                push    EBX
+                mov     EBX,blockaddr
+                push    EBP
+                mov     EBP,catch_ebp
+                call    EBX
+                pop     EBP
+                pop     EBX
+            }
+        }
+    }
+
+    _asm
+    {
+        pop     FS:_except_list
+        add     ESP,12
+    }
+}
+
+/***********************************
+ * external version of the unwinder
+ */
+
+__declspec(naked) void __cdecl _d_local_unwind2()
+{
+    __asm
+    {
+        jmp     _d_local_unwind
+    }
+}
+
+/***********************************
+ * The frame handler, this is called for each frame that has been registered
+ * in the OS except_list.
+ * Input:
+ *      EAX     the handler table for the frame
+ */
+
+EXCEPTION_DISPOSITION _d_monitor_handler(
+            EXCEPTION_RECORD *exception_record,
+            struct DEstablisherFrame *frame,
+            CONTEXT context,
+            void *dispatcher_context)
+{
+    if (exception_record->ExceptionFlags & EXCEPTION_UNWIND)
+    {
+        _d_monitorexit((Object *)frame->table_index);
+    }
+    else
+    {
+    }
+    return ExceptionContinueSearch;
+}
+
+/***********************************
+ */
+
+void _d_monitor_prolog(void *x, void *y, Object *h)
+{
+    __asm
+    {
+        push    EAX
+    }
+    //printf("_d_monitor_prolog(x=%p, y=%p, h=%p)\n", x, y, h);
+    _d_monitorenter(h);
+    __asm
+    {
+        pop     EAX
+    }
+}
+
+/***********************************
+ */
+
+void _d_monitor_epilog(void *x, void *y, Object *h)
+{
+    //printf("_d_monitor_epilog(x=%p, y=%p, h=%p)\n", x, y, h);
+    __asm
+    {
+        push    EAX
+        push    EDX
+    }
+    _d_monitorexit(h);
+    __asm
+    {
+        pop     EDX
+        pop     EAX
+    }
+}
+
+#endif
+
+/* ======================== linux =============================== */
+
+#if linux
+
+#include        "mars.h"
+
+extern ClassInfo D6object9Throwable7__ClassZ;
+#define _Class_9Throwable D6object9Throwable7__ClassZ;
+
+extern ClassInfo D6object5Error7__ClassZ;
+#define _Class_5Error D6object5Error7__ClassZ
+
+typedef int (*fp_t)();   // function pointer in ambient memory model
+
+struct DHandlerInfo
+{
+    unsigned offset;            // offset from function address to start of guarded section
+    int prev_index;             // previous table index
+    unsigned cioffset;          // offset to DCatchInfo data from start of table (!=0 if try-catch)
+    void *finally_code;         // pointer to finally code to execute
+                                // (!=0 if try-finally)
+};
+
+// Address of DHandlerTable, searched for by eh_finddata()
+
+struct DHandlerTable
+{
+    void *fptr;                 // pointer to start of function
+    unsigned espoffset;         // offset of ESP from EBP
+    unsigned retoffset;         // offset from start of function to return code
+    unsigned nhandlers;         // dimension of handler_info[]
+    struct DHandlerInfo handler_info[1];
+};
+
+struct DCatchBlock
+{
+    ClassInfo *type;            // catch type
+    unsigned bpoffset;          // EBP offset of catch var
+    void *code;                 // catch handler code
+};
+
+// Create one of these for each try-catch
+struct DCatchInfo
+{
+    unsigned ncatches;                  // number of catch blocks
+    struct DCatchBlock catch_block[1];  // data for each catch block
+};
+
+// One of these is generated for each function with try-catch or try-finally
+
+struct FuncTable
+{
+    void *fptr;                 // pointer to start of function
+    struct DHandlerTable *handlertable; // eh data for this function
+    unsigned size;              // size of function in bytes
+};
+
+extern struct FuncTable *table_start;
+extern struct FuncTable *table_end;
+
+void terminate()
+{
+//    _asm
+//    {
+//      hlt
+//    }
+}
+
+/*******************************************
+ * Given address that is inside a function,
+ * figure out which function it is in.
+ * Return DHandlerTable if there is one, NULL if not.
+ */
+
+struct DHandlerTable *__eh_finddata(void *address)
+{
+    struct FuncTable *ft;
+
+    for (ft = (struct FuncTable *)table_start;
+         ft < (struct FuncTable *)table_end;
+         ft++)
+    {
+        if (ft->fptr <= address &&
+            address < (void *)((char *)ft->fptr + ft->size))
+        {
+            return ft->handlertable;
+        }
+    }
+    return NULL;
+}
+
+
+/******************************
+ * Given EBP, find return address to caller, and caller's EBP.
+ * Input:
+ *   regbp       Value of EBP for current function
+ *   *pretaddr   Return address
+ * Output:
+ *   *pretaddr   return address to caller
+ * Returns:
+ *   caller's EBP
+ */
+
+unsigned __eh_find_caller(unsigned regbp, unsigned *pretaddr)
+{
+    unsigned bp = *(unsigned *)regbp;
+
+    if (bp)         // if not end of call chain
+    {
+        // Perform sanity checks on new EBP.
+        // If it is screwed up, terminate() hopefully before we do more damage.
+        if (bp <= regbp)
+            // stack should grow to smaller values
+            terminate();
+
+        *pretaddr = *(unsigned *)(regbp + sizeof(int));
+    }
+    return bp;
+}
+
+/***********************************
+ * Throw a D object.
+ */
+
+void __stdcall _d_throw(Object *h)
+{
+    unsigned regebp;
+
+    //printf("_d_throw(h = %p, &h = %p)\n", h, &h);
+    //printf("\tvptr = %p\n", *(void **)h);
+
+    regebp = _EBP;
+
+    while (1)           // for each function on the stack
+    {
+        struct DHandlerTable *handler_table;
+        struct FuncTable *pfunc;
+        struct DHandlerInfo *phi;
+        unsigned retaddr;
+        unsigned funcoffset;
+        unsigned spoff;
+        unsigned retoffset;
+        int index;
+        int dim;
+        int ndx;
+        int prev_ndx;
+
+        regebp = __eh_find_caller(regebp,&retaddr);
+        if (!regebp)
+            // if end of call chain
+            break;
+
+        handler_table = __eh_finddata((void *)retaddr);   // find static data associated with function
+        if (!handler_table)         // if no static data
+        {
+            continue;
+        }
+        funcoffset = (unsigned)handler_table->fptr;
+        spoff = handler_table->espoffset;
+        retoffset = handler_table->retoffset;
+
+#ifdef DEBUG
+        printf("retaddr = x%x\n",(unsigned)retaddr);
+        printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n",
+        regebp,funcoffset,spoff,retoffset);
+#endif
+
+        // Find start index for retaddr in static data
+        dim = handler_table->nhandlers;
+        index = -1;
+        for (int i = 0; i < dim; i++)
+        {
+            phi = &handler_table->handler_info[i];
+
+            if ((unsigned)retaddr >= funcoffset + phi->offset)
+                index = i;
+        }
+
+        // walk through handler table, checking each handler
+        // with an index smaller than the current table_index
+        for (ndx = index; ndx != -1; ndx = prev_ndx)
+        {
+            phi = &handler_table->handler_info[ndx];
+            prev_ndx = phi->prev_index;
+            if (phi->cioffset)
+            {
+                // this is a catch handler (no finally)
+                struct DCatchInfo *pci;
+                int ncatches;
+                int i;
+
+                pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset);
+                ncatches = pci->ncatches;
+                for (i = 0; i < ncatches; i++)
+                {
+                    struct DCatchBlock *pcb;
+                    ClassInfo *ci = **(ClassInfo ***)h;
+
+                    pcb = &pci->catch_block[i];
+
+                    if (_d_isbaseof(ci, pcb->type))
+                    {   // Matched the catch type, so we've found the handler.
+
+                        // Initialize catch variable
+                        *(void **)(regebp + (pcb->bpoffset)) = h;
+
+                        // Jump to catch block. Does not return.
+                        {
+                            unsigned catch_esp;
+                            fp_t catch_addr;
+
+                            catch_addr = (fp_t)(pcb->code);
+                            catch_esp = regebp - handler_table->espoffset - sizeof(fp_t);
+                            _asm
+                            {
+                                mov     EAX,catch_esp
+                                mov     ECX,catch_addr
+                                mov     [EAX],ECX
+                                mov     EBP,regebp
+                                mov     ESP,EAX         // reset stack
+                                ret                     // jump to catch block
+                            }
+                        }
+                    }
+                }
+            }
+            else if (phi->finally_code)
+            {   // Call finally block
+                // Note that it is unnecessary to adjust the ESP, as the finally block
+                // accesses all items on the stack as relative to EBP.
+
+                void *blockaddr = phi->finally_code;
+
+                _asm
+                {
+                    push        EBX
+                    mov         EBX,blockaddr
+                    push        EBP
+                    mov         EBP,regebp
+                    call        EBX
+                    pop         EBP
+                    pop         EBX
+                }
+            }
+        }
+    }
+}
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/deh2.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,316 @@
+/**
+ * Implementation of exception handling support routines for Posix.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.deh2;
+
+//debug=1;
+
+extern (C)
+{
+    extern __gshared
+    {
+	void* _deh_beg;
+	void* _deh_end;
+    }
+
+    int _d_isbaseof(ClassInfo oc, ClassInfo c);
+}
+
+alias int (*fp_t)();   // function pointer in ambient memory model
+
+struct DHandlerInfo
+{
+    uint offset;                // offset from function address to start of guarded section
+    uint endoffset;             // offset of end of guarded section
+    int prev_index;             // previous table index
+    uint cioffset;              // offset to DCatchInfo data from start of table (!=0 if try-catch)
+    void *finally_code;         // pointer to finally code to execute
+                                // (!=0 if try-finally)
+}
+
+// Address of DHandlerTable, searched for by eh_finddata()
+
+struct DHandlerTable
+{
+    void *fptr;                 // pointer to start of function
+    uint espoffset;             // offset of ESP from EBP
+    uint retoffset;             // offset from start of function to return code
+    uint nhandlers;             // dimension of handler_info[]
+    DHandlerInfo handler_info[1];
+}
+
+struct DCatchBlock
+{
+    ClassInfo type;             // catch type
+    uint bpoffset;              // EBP offset of catch var
+    void *code;                 // catch handler code
+}
+
+// Create one of these for each try-catch
+struct DCatchInfo
+{
+    uint ncatches;                      // number of catch blocks
+    DCatchBlock catch_block[1];         // data for each catch block
+}
+
+// One of these is generated for each function with try-catch or try-finally
+
+struct FuncTable
+{
+    void *fptr;                 // pointer to start of function
+    DHandlerTable *handlertable; // eh data for this function
+    uint fsize;         // size of function in bytes
+}
+
+void terminate()
+{
+    asm
+    {
+        hlt ;
+    }
+}
+
+/*******************************************
+ * Given address that is inside a function,
+ * figure out which function it is in.
+ * Return DHandlerTable if there is one, NULL if not.
+ */
+
+DHandlerTable *__eh_finddata(void *address)
+{
+    FuncTable *ft;
+
+//    debug printf("__eh_finddata(address = x%x)\n", address);
+//    debug printf("_deh_beg = x%x, _deh_end = x%x\n", &_deh_beg, &_deh_end);
+    for (ft = cast(FuncTable *)&_deh_beg;
+         ft < cast(FuncTable *)&_deh_end;
+         ft++)
+    {
+//      debug printf("\tfptr = x%x, fsize = x%03x, handlertable = x%x\n",
+//              ft.fptr, ft.fsize, ft.handlertable);
+
+        if (ft.fptr <= address &&
+            address < cast(void *)(cast(char *)ft.fptr + ft.fsize))
+        {
+//          debug printf("\tfound handler table\n");
+            return ft.handlertable;
+        }
+    }
+//    debug printf("\tnot found\n");
+    return null;
+}
+
+
+/******************************
+ * Given EBP, find return address to caller, and caller's EBP.
+ * Input:
+ *   regbp       Value of EBP for current function
+ *   *pretaddr   Return address
+ * Output:
+ *   *pretaddr   return address to caller
+ * Returns:
+ *   caller's EBP
+ */
+
+uint __eh_find_caller(uint regbp, uint *pretaddr)
+{
+    uint bp = *cast(uint *)regbp;
+
+    if (bp)         // if not end of call chain
+    {
+        // Perform sanity checks on new EBP.
+        // If it is screwed up, terminate() hopefully before we do more damage.
+        if (bp <= regbp)
+            // stack should grow to smaller values
+            terminate();
+
+        *pretaddr = *cast(uint *)(regbp + int.sizeof);
+    }
+    return bp;
+}
+
+/***********************************
+ * Throw a D object.
+ */
+
+extern (Windows) void _d_throw(Object *h)
+{
+    uint regebp;
+
+    debug
+    {
+        printf("_d_throw(h = %p, &h = %p)\n", h, &h);
+        printf("\tvptr = %p\n", *cast(void **)h);
+    }
+
+    asm
+    {
+        mov regebp,EBP  ;
+    }
+
+//static uint abc;
+//if (++abc == 2) *(char *)0=0;
+
+//int count = 0;
+    while (1)           // for each function on the stack
+    {
+        DHandlerTable *handler_table;
+        FuncTable *pfunc;
+        DHandlerInfo *phi;
+        uint retaddr;
+        uint funcoffset;
+        uint spoff;
+        uint retoffset;
+        int index;
+        int dim;
+        int ndx;
+        int prev_ndx;
+
+        regebp = __eh_find_caller(regebp,&retaddr);
+        if (!regebp)
+        {   // if end of call chain
+            debug printf("end of call chain\n");
+            break;
+        }
+
+        debug printf("found caller, EBP = x%x, retaddr = x%x\n", regebp, retaddr);
+//if (++count == 12) *(char*)0=0;
+        handler_table = __eh_finddata(cast(void *)retaddr);   // find static data associated with function
+        if (!handler_table)         // if no static data
+        {
+            debug printf("no handler table\n");
+            continue;
+        }
+        funcoffset = cast(uint)handler_table.fptr;
+        spoff = handler_table.espoffset;
+        retoffset = handler_table.retoffset;
+
+        debug
+        {
+            printf("retaddr = x%x\n",cast(uint)retaddr);
+            printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n",
+            regebp,funcoffset,spoff,retoffset);
+        }
+
+        // Find start index for retaddr in static data
+        dim = handler_table.nhandlers;
+
+        debug
+        {
+            printf("handler_info[]:\n");
+            for (int i = 0; i < dim; i++)
+            {
+                phi = &handler_table.handler_info[i];
+                printf("\t[%d]: offset = x%04x, endoffset = x%04x, prev_index = %d, cioffset = x%04x, finally_code = %x\n",
+                        i, phi.offset, phi.endoffset, phi.prev_index, phi.cioffset, phi.finally_code);
+            }
+        }
+
+        index = -1;
+        for (int i = 0; i < dim; i++)
+        {
+            phi = &handler_table.handler_info[i];
+
+            debug printf("i = %d, phi.offset = %04x\n", i, funcoffset + phi.offset);
+            if (cast(uint)retaddr > funcoffset + phi.offset &&
+                cast(uint)retaddr <= funcoffset + phi.endoffset)
+                index = i;
+        }
+        debug printf("index = %d\n", index);
+
+        // walk through handler table, checking each handler
+        // with an index smaller than the current table_index
+        for (ndx = index; ndx != -1; ndx = prev_ndx)
+        {
+            phi = &handler_table.handler_info[ndx];
+            prev_ndx = phi.prev_index;
+            if (phi.cioffset)
+            {
+                // this is a catch handler (no finally)
+                DCatchInfo *pci;
+                int ncatches;
+                int i;
+
+                pci = cast(DCatchInfo *)(cast(char *)handler_table + phi.cioffset);
+                ncatches = pci.ncatches;
+                for (i = 0; i < ncatches; i++)
+                {
+                    DCatchBlock *pcb;
+                    ClassInfo ci = **cast(ClassInfo **)h;
+
+                    pcb = &pci.catch_block[i];
+
+                    if (_d_isbaseof(ci, pcb.type))
+                    {   // Matched the catch type, so we've found the handler.
+
+                        // Initialize catch variable
+                        *cast(void **)(regebp + (pcb.bpoffset)) = h;
+
+                        // Jump to catch block. Does not return.
+                        {
+                            uint catch_esp;
+                            fp_t catch_addr;
+
+                            catch_addr = cast(fp_t)(pcb.code);
+                            catch_esp = regebp - handler_table.espoffset - fp_t.sizeof;
+                            asm
+                            {
+                                mov     EAX,catch_esp   ;
+                                mov     ECX,catch_addr  ;
+                                mov     [EAX],ECX       ;
+                                mov     EBP,regebp      ;
+                                mov     ESP,EAX         ; // reset stack
+                                ret                     ; // jump to catch block
+                            }
+                        }
+                    }
+                }
+            }
+            else if (phi.finally_code)
+            {   // Call finally block
+                // Note that it is unnecessary to adjust the ESP, as the finally block
+                // accesses all items on the stack as relative to EBP.
+
+                void *blockaddr = phi.finally_code;
+
+                version (OSX)
+                {
+                    asm
+                    {
+                        sub     ESP,4           ; // align stack to 16
+                        push    EBX             ;
+                        mov     EBX,blockaddr   ;
+                        push    EBP             ;
+                        mov     EBP,regebp      ;
+                        call    EBX             ;
+                        pop     EBP             ;
+                        pop     EBX             ;
+                        add     ESP,4           ;
+                    }
+                }
+                else
+                {
+                    asm
+                    {
+                        push        EBX             ;
+                        mov         EBX,blockaddr   ;
+                        push        EBP             ;
+                        mov         EBP,regebp      ;
+                        call        EBX             ;
+                        pop         EBP             ;
+                        pop         EBX             ;
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/dmain2.BAK	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,374 @@
+/*
+ * Placed into the Public Domain.
+ * written by Walter Bright
+ * www.digitalmars.com
+ */
+
+/*
+ *  Modified by Sean Kelly for use with the D Runtime Project
+ */
+
+module rt.dmain2;
+
+private
+{
+    import memory;
+    import util.console;
+    import core.stdc.stddef;
+    import core.stdc.stdlib;
+    import core.stdc.string;
+}
+
+version (Windows)
+{
+    extern (Windows) alias int function() FARPROC;
+    extern (Windows) FARPROC    GetProcAddress(void*, in char*);
+    extern (Windows) void*      LoadLibraryA(in char*);
+    extern (Windows) int        FreeLibrary(void*);
+    extern (Windows) void*      LocalFree(void*);
+    extern (Windows) wchar_t*   GetCommandLineW();
+    extern (Windows) wchar_t**  CommandLineToArgvW(wchar_t*, int*);
+    extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
+    pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW
+}
+
+extern (C) void _STI_monitor_staticctor();
+extern (C) void _STD_monitor_staticdtor();
+extern (C) void _STI_critical_init();
+extern (C) void _STD_critical_term();
+extern (C) void gc_init();
+extern (C) void gc_term();
+extern (C) void _minit();
+extern (C) void _moduleCtor();
+extern (C) void _moduleDtor();
+extern (C) void thread_joinAll();
+
+/***********************************
+ * These are a temporary means of providing a GC hook for DLL use.  They may be
+ * replaced with some other similar functionality later.
+ */
+extern (C)
+{
+    void* gc_getProxy();
+    void  gc_setProxy(void* p);
+    void  gc_clrProxy();
+
+    alias void* function()      gcGetFn;
+    alias void  function(void*) gcSetFn;
+    alias void  function()      gcClrFn;
+}
+
+extern (C) void* rt_loadLibrary(in char[] name)
+{
+    version (Windows)
+    {
+        char[260] temp = void;
+        temp[0 .. name.length] = name[];
+        temp[name.length] = cast(char) 0;
+        void* ptr = LoadLibraryA(temp.ptr);
+        if (ptr is null)
+            return ptr;
+        gcSetFn gcSet = cast(gcSetFn) GetProcAddress(ptr, "gc_setProxy");
+        if (gcSet !is null)
+            gcSet(gc_getProxy());
+        return ptr;
+
+    }
+    else version (linux)
+    {
+        throw new Exception("rt_loadLibrary not yet implemented on linux.");
+    }
+}
+
+extern (C) bool rt_unloadLibrary(void* ptr)
+{
+    version (Windows)
+    {
+        gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy");
+        if (gcClr !is null)
+            gcClr();
+        return FreeLibrary(ptr) != 0;
+    }
+    else version (linux)
+    {
+        throw new Exception("rt_unloadLibrary not yet implemented on linux.");
+    }
+}
+
+/***********************************
+ * These functions must be defined for any D program linked
+ * against this library.
+ */
+extern (C) void onAssertError(string file, size_t line);
+extern (C) void onAssertErrorMsg(string file, size_t line, string msg);
+extern (C) void onRangeError(string file, size_t line);
+extern (C) void onHiddenFuncError(Object o);
+extern (C) void onSwitchError(string file, size_t line);
+extern (C) bool runModuleUnitTests();
+
+// this function is called from the utf module
+//extern (C) void onUnicodeError(string msg, size_t idx);
+
+/***********************************
+ * These are internal callbacks for various language errors.
+ */
+extern (C) void _d_assert(string file, uint line)
+{
+    onAssertError(file, line);
+}
+
+extern (C) static void _d_assert_msg(string msg, string file, uint line)
+{
+    onAssertErrorMsg(file, line, msg);
+}
+
+extern (C) void _d_array_bounds(string file, uint line)
+{
+    onRangeError(file, line);
+}
+
+extern (C) void _d_switch_error(string file, uint line)
+{
+    onSwitchError(file, line);
+}
+
+extern (C) void _d_hidden_func()
+{
+    Object o;
+    asm
+    {
+        mov o, EAX;
+    }
+    onHiddenFuncError(o);
+}
+
+bool _d_isHalting = false;
+
+extern (C) bool rt_isHalting()
+{
+    return _d_isHalting;
+}
+
+extern (C) bool rt_trapExceptions = true;
+
+void _d_criticalInit()
+{
+    version (linux)
+    {
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+}
+
+alias void delegate(Throwable) ExceptionHandler;
+
+extern (C) bool rt_init(ExceptionHandler dg = null)
+{
+    _d_criticalInit();
+
+    try
+    {
+        gc_init();
+        initStaticDataGC();
+        version (Windows)
+            _minit();
+        _moduleCtor();
+        return true;
+    }
+    catch (Throwable e)
+    {
+        if (dg)
+            dg(e);
+    }
+    catch
+    {
+
+    }
+    _d_criticalTerm();
+    return false;
+}
+
+void _d_criticalTerm()
+{
+    version (linux)
+    {
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+}
+
+extern (C) bool rt_term(ExceptionHandler dg = null)
+{
+    try
+    {
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+        return true;
+    }
+    catch (Throwable e)
+    {
+        if (dg)
+            dg(e);
+    }
+    catch
+    {
+
+    }
+    finally
+    {
+        _d_criticalTerm();
+    }
+    return false;
+}
+
+/***********************************
+ * The D main() function supplied by the user's program
+ */
+int main(char[][] args);
+
+/***********************************
+ * Substitutes for the C main() function.
+ * It's purpose is to wrap the call to the D main()
+ * function and catch any unhandled exceptions.
+ */
+
+extern (C) int main(int argc, char **argv)
+{
+    char[][] args;
+    int result;
+
+    version (linux)
+    {
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+
+    version (Windows)
+    {
+        wchar_t*  wcbuf = GetCommandLineW();
+        size_t    wclen = wcslen(wcbuf);
+        int       wargc = 0;
+        wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
+        assert(wargc == argc);
+
+        char*     cargp = null;
+        size_t    cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
+
+        cargp = cast(char*) alloca(cargl);
+        args  = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
+
+        for (size_t i = 0, p = 0; i < wargc; i++)
+        {
+            int wlen = wcslen(wargs[i]);
+            int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
+            args[i]  = cargp[p .. p+clen];
+            p += clen; assert(p <= cargl);
+            WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
+        }
+        LocalFree(wargs);
+        wargs = null;
+        wargc = 0;
+    }
+    else version (linux)
+    {
+        char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
+        scope(exit) free(am);
+
+        for (size_t i = 0; i < argc; i++)
+        {
+            auto len = strlen(argv[i]);
+            am[i] = argv[i][0 .. len];
+        }
+        args = am[0 .. argc];
+    }
+
+    bool trapExceptions = rt_trapExceptions;
+
+    void tryExec(void delegate() dg)
+    {
+
+        if (trapExceptions)
+        {
+            try
+            {
+                dg();
+            }
+            catch (Throwable e)
+            {
+                while (e)
+                {
+                    if (e.file)
+                    {
+                        // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg);
+                        console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
+                    }
+                    else
+                    {
+                        // fprintf(stderr, "%.*s\n", e.toString());
+                        console (e.toString)("\n");
+                    }
+                    if (e.info)
+                    {
+                        console ("----------------\n");
+                        foreach (t; e.info)
+                            console (t)("\n");
+                    }
+                    if (e.next)
+                        console ("\n");
+                    e = e.next;
+                }
+                result = EXIT_FAILURE;
+            }
+            catch (Object o)
+            {
+                // fprintf(stderr, "%.*s\n", o.toString());
+                console (o.toString)("\n");
+                result = EXIT_FAILURE;
+            }
+        }
+        else
+        {
+            dg();
+        }
+    }
+
+    // NOTE: The lifetime of a process is much like the lifetime of an object:
+    //       it is initialized, then used, then destroyed.  If initialization
+    //       fails, the successive two steps are never reached.  However, if
+    //       initialization succeeds, then cleanup will occur even if the use
+    //       step fails in some way.  Here, the use phase consists of running
+    //       the user's main function.  If main terminates with an exception,
+    //       the exception is handled and then cleanup begins.  An exception
+    //       thrown during cleanup, however, will abort the cleanup process.
+
+    void runMain()
+    {
+        result = main(args);
+    }
+
+    void runAll()
+    {
+        gc_init();
+        initStaticDataGC();
+        version (Windows)
+            _minit();
+        _moduleCtor();
+        if (runModuleUnitTests())
+            tryExec(&runMain);
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+    }
+
+    tryExec(&runAll);
+
+    version (linux)
+    {
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/dmain2.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,394 @@
+/**
+ * Contains main program entry point and support routines.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.dmain2;
+
+private
+{
+    import rt.memory;
+    import rt.util.console;
+    import core.stdc.stddef;
+    import core.stdc.stdlib;
+    import core.stdc.string;
+}
+
+version (Windows)
+{
+    private import core.stdc.wchar_;
+
+    extern (Windows) alias int function() FARPROC;
+    extern (Windows) FARPROC    GetProcAddress(void*, in char*);
+    extern (Windows) void*      LoadLibraryA(in char*);
+    extern (Windows) int        FreeLibrary(void*);
+    extern (Windows) void*      LocalFree(void*);
+    extern (Windows) wchar_t*   GetCommandLineW();
+    extern (Windows) wchar_t**  CommandLineToArgvW(wchar_t*, int*);
+    extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
+    pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW
+}
+
+extern (C) void _STI_monitor_staticctor();
+extern (C) void _STD_monitor_staticdtor();
+extern (C) void _STI_critical_init();
+extern (C) void _STD_critical_term();
+extern (C) void gc_init();
+extern (C) void gc_term();
+extern (C) void _minit();
+extern (C) void _moduleCtor();
+extern (C) void _moduleDtor();
+extern (C) void thread_joinAll();
+
+version (OSX)
+{
+    // The bottom of the stack
+    extern (C) void* __osx_stack_end = cast(void*)0xC0000000;
+}
+
+/***********************************
+ * These are a temporary means of providing a GC hook for DLL use.  They may be
+ * replaced with some other similar functionality later.
+ */
+extern (C)
+{
+    void* gc_getProxy();
+    void  gc_setProxy(void* p);
+    void  gc_clrProxy();
+
+    alias void* function()      gcGetFn;
+    alias void  function(void*) gcSetFn;
+    alias void  function()      gcClrFn;
+}
+
+extern (C) void* rt_loadLibrary(in char[] name)
+{
+    version (Windows)
+    {
+        char[260] temp = void;
+        temp[0 .. name.length] = name[];
+        temp[name.length] = cast(char) 0;
+        void* ptr = LoadLibraryA(temp.ptr);
+        if (ptr is null)
+            return ptr;
+        gcSetFn gcSet = cast(gcSetFn) GetProcAddress(ptr, "gc_setProxy");
+        if (gcSet !is null)
+            gcSet(gc_getProxy());
+        return ptr;
+
+    }
+    else version (Posix)
+    {
+        throw new Exception("rt_loadLibrary not yet implemented on Posix.");
+    }
+}
+
+extern (C) bool rt_unloadLibrary(void* ptr)
+{
+    version (Windows)
+    {
+        gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy");
+        if (gcClr !is null)
+            gcClr();
+        return FreeLibrary(ptr) != 0;
+    }
+    else version (Posix)
+    {
+        throw new Exception("rt_unloadLibrary not yet implemented on Posix.");
+    }
+}
+
+/***********************************
+ * These functions must be defined for any D program linked
+ * against this library.
+ */
+extern (C) void onAssertError(string file, size_t line);
+extern (C) void onAssertErrorMsg(string file, size_t line, string msg);
+extern (C) void onRangeError(string file, size_t line);
+extern (C) void onHiddenFuncError(Object o);
+extern (C) void onSwitchError(string file, size_t line);
+extern (C) bool runModuleUnitTests();
+
+// this function is called from the utf module
+//extern (C) void onUnicodeError(string msg, size_t idx);
+
+/***********************************
+ * These are internal callbacks for various language errors.
+ */
+extern (C) void _d_assert(string file, uint line)
+{
+    onAssertError(file, line);
+}
+
+extern (C) static void _d_assert_msg(string msg, string file, uint line)
+{
+    onAssertErrorMsg(file, line, msg);
+}
+
+extern (C) void _d_array_bounds(string file, uint line)
+{
+    onRangeError(file, line);
+}
+
+extern (C) void _d_switch_error(string file, uint line)
+{
+    onSwitchError(file, line);
+}
+
+extern (C) void _d_hidden_func()
+{
+    Object o;
+    asm
+    {
+        mov o, EAX;
+    }
+    onHiddenFuncError(o);
+}
+
+shared bool _d_isHalting = false;
+
+extern (C) bool rt_isHalting()
+{
+    return _d_isHalting;
+}
+
+extern (C) shared bool rt_trapExceptions = true;
+
+void _d_criticalInit()
+{
+    version (Posix)
+    {
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+}
+
+alias void delegate(Throwable) ExceptionHandler;
+
+extern (C) bool rt_init(ExceptionHandler dg = null)
+{
+    _d_criticalInit();
+
+    try
+    {
+        gc_init();
+        initStaticDataGC();
+        version (Windows)
+            _minit();
+        _moduleCtor();
+        runModuleUnitTests();
+        return true;
+    }
+    catch (Throwable e)
+    {
+        if (dg)
+            dg(e);
+    }
+    catch
+    {
+
+    }
+    _d_criticalTerm();
+    return false;
+}
+
+void _d_criticalTerm()
+{
+    version (Posix)
+    {
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+}
+
+extern (C) bool rt_term(ExceptionHandler dg = null)
+{
+    try
+    {
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+        return true;
+    }
+    catch (Throwable e)
+    {
+        if (dg)
+            dg(e);
+    }
+    catch
+    {
+
+    }
+    finally
+    {
+        _d_criticalTerm();
+    }
+    return false;
+}
+
+/***********************************
+ * The D main() function supplied by the user's program
+ */
+int main(char[][] args);
+
+/***********************************
+ * Substitutes for the C main() function.
+ * It's purpose is to wrap the call to the D main()
+ * function and catch any unhandled exceptions.
+ */
+
+extern (C) int main(int argc, char **argv)
+{
+    char[][] args;
+    int result;
+
+    version (OSX)
+    {   /* OSX does not provide a way to get at the top of the
+         * stack, except for the magic value 0xC0000000.
+         * But as far as the gc is concerned, argv is at the top
+         * of the main thread's stack, so save the address of that.
+         */
+        __osx_stack_end = cast(void*)&argv;
+    }
+
+    version (Posix)
+    {
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+
+    version (Windows)
+    {
+        wchar_t*  wcbuf = GetCommandLineW();
+        size_t    wclen = wcslen(wcbuf);
+        int       wargc = 0;
+        wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
+        assert(wargc == argc);
+
+        char*     cargp = null;
+        size_t    cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
+
+        cargp = cast(char*) alloca(cargl);
+        args  = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
+
+        for (size_t i = 0, p = 0; i < wargc; i++)
+        {
+            int wlen = wcslen(wargs[i]);
+            int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
+            args[i]  = cargp[p .. p+clen];
+            p += clen; assert(p <= cargl);
+            WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
+        }
+        LocalFree(wargs);
+        wargs = null;
+        wargc = 0;
+    }
+    else version (Posix)
+    {
+        char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
+        scope(exit) free(am);
+
+        for (size_t i = 0; i < argc; i++)
+        {
+            auto len = strlen(argv[i]);
+            am[i] = argv[i][0 .. len];
+        }
+        args = am[0 .. argc];
+    }
+
+    bool trapExceptions = rt_trapExceptions;
+
+    void tryExec(scope void delegate() dg)
+    {
+
+        if (trapExceptions)
+        {
+            try
+            {
+                dg();
+            }
+            catch (Throwable e)
+            {
+                while (e)
+                {
+                    if (e.file)
+                    {
+                        // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg);
+                        console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
+                    }
+                    else
+                    {
+                        // fprintf(stderr, "%.*s\n", e.toString());
+                        console (e.toString)("\n");
+                    }
+                    if (e.info)
+                    {
+                        console ("----------------\n");
+                        foreach (t; e.info)
+                            console (t)("\n");
+                    }
+                    if (e.next)
+                        console ("\n");
+                    e = e.next;
+                }
+                result = EXIT_FAILURE;
+            }
+            catch (Object o)
+            {
+                // fprintf(stderr, "%.*s\n", o.toString());
+                console (o.toString)("\n");
+                result = EXIT_FAILURE;
+            }
+        }
+        else
+        {
+            dg();
+        }
+    }
+
+    // NOTE: The lifetime of a process is much like the lifetime of an object:
+    //       it is initialized, then used, then destroyed.  If initialization
+    //       fails, the successive two steps are never reached.  However, if
+    //       initialization succeeds, then cleanup will occur even if the use
+    //       step fails in some way.  Here, the use phase consists of running
+    //       the user's main function.  If main terminates with an exception,
+    //       the exception is handled and then cleanup begins.  An exception
+    //       thrown during cleanup, however, will abort the cleanup process.
+
+    void runMain()
+    {
+        result = main(args);
+    }
+
+    void runAll()
+    {
+        gc_init();
+        initStaticDataGC();
+        version (Windows)
+            _minit();
+        _moduleCtor();
+        if (runModuleUnitTests())
+            tryExec(&runMain);
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+    }
+
+    tryExec(&runAll);
+
+    version (Posix)
+    {
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/genobj.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,1597 @@
+/**
+ * Forms the symbols available to all D programs. Includes Object, which is
+ * the root of the class object hierarchy.  This module is implicitly
+ * imported.
+ * Macros:
+ *      WIKI = Object
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+module object;
+
+private
+{
+    import core.stdc.string;
+    import core.stdc.stdlib;
+    import util.string;
+    debug(PRINTF) import core.stdc.stdio;
+
+    extern (C) void onOutOfMemoryError();
+    extern (C) Object _d_newclass(ClassInfo ci);
+}
+
+// NOTE: For some reason, this declaration method doesn't work
+//       in this particular file (and this file only).  It must
+//       be a DMD thing.
+//alias typeof(int.sizeof)                    size_t;
+//alias typeof(cast(void*)0 - cast(void*)0)   ptrdiff_t;
+
+version(X86_64)
+{
+    alias ulong size_t;
+    alias long  ptrdiff_t;
+}
+else
+{
+    alias uint  size_t;
+    alias int   ptrdiff_t;
+}
+
+alias size_t hash_t;
+alias bool equals_t;
+
+alias immutable(char)[]  string;
+alias immutable(wchar)[] wstring;
+alias immutable(dchar)[] dstring;
+
+/**
+ * All D class objects inherit from Object.
+ */
+class Object
+{
+    /**
+     * Convert Object to a human readable string.
+     */
+    string toString()
+    {
+        return this.classinfo.name;
+    }
+
+    /**
+     * Compute hash function for Object.
+     */
+    hash_t toHash()
+    {
+        // BUG: this prevents a compacting GC from working, needs to be fixed
+        return cast(hash_t)cast(void*)this;
+    }
+
+    /**
+     * Compare with another Object obj.
+     * Returns:
+     *  $(TABLE
+     *  $(TR $(TD this &lt; obj) $(TD &lt; 0))
+     *  $(TR $(TD this == obj) $(TD 0))
+     *  $(TR $(TD this &gt; obj) $(TD &gt; 0))
+     *  )
+     */
+    int opCmp(Object o)
+    {
+        // BUG: this prevents a compacting GC from working, needs to be fixed
+        //return cast(int)cast(void*)this - cast(int)cast(void*)o;
+
+        throw new Exception("need opCmp for class " ~ this.classinfo.name);
+        //return this !is o;
+    }
+
+    /**
+     * Returns !=0 if this object does have the same contents as obj.
+     */
+    equals_t opEquals(Object o)
+    {
+        return this is o;
+    }
+
+    interface Monitor
+    {
+        void lock();
+        void unlock();
+    }
+
+    /**
+     * Create instance of class specified by classname.
+     * The class must either have no constructors or have
+     * a default constructor.
+     * Returns:
+     *   null if failed
+     */
+    static Object factory(string classname)
+    {
+        auto ci = ClassInfo.find(classname);
+        if (ci)
+        {
+            return ci.create();
+        }
+        return null;
+    }
+}
+
+/**
+ * Information about an interface.
+ * When an object is accessed via an interface, an Interface* appears as the
+ * first entry in its vtbl.
+ */
+struct Interface
+{
+    ClassInfo   classinfo;  /// .classinfo for this interface (not for containing class)
+    void*[]     vtbl;
+    ptrdiff_t   offset;     /// offset to Interface 'this' from Object 'this'
+}
+
+/**
+ * Runtime type information about a class. Can be retrieved for any class type
+ * or instance by using the .classinfo property.
+ * A pointer to this appears as the first entry in the class's vtbl[].
+ */
+class ClassInfo : Object
+{
+    byte[]      init;           /** class static initializer
+                                 * (init.length gives size in bytes of class)
+                                 */
+    string      name;           /// class name
+    void*[]     vtbl;           /// virtual function pointer table
+    Interface[] interfaces;     /// interfaces this class implements
+    ClassInfo   base;           /// base class
+    void*       destructor;
+    void*	 classInvariant;
+    uint        flags;
+    //  1:                      // is IUnknown or is derived from IUnknown
+    //  2:                      // has no possible pointers into GC memory
+    //  4:                      // has offTi[] member
+    //  8:                      // has constructors
+    // 16:                      // has xgetMembers member
+    // 32:                      // has typeinfo member
+    void*       deallocator;
+    OffsetTypeInfo[] offTi;
+    void*	 defaultConstructor;   // default Constructor
+    const(MemberInfo[]) function(in char[]) xgetMembers;
+    TypeInfo typeinfo;
+
+    /**
+     * Search all modules for ClassInfo corresponding to classname.
+     * Returns: null if not found
+     */
+    static ClassInfo find(in char[] classname)
+    {
+        foreach (m; ModuleInfo)
+        {
+            //writefln("module %s, %d", m.name, m.localClasses.length);
+            foreach (c; m.localClasses)
+            {
+                //writefln("\tclass %s", c.name);
+                if (c.name == classname)
+                    return c;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Create instance of Object represented by 'this'.
+     */
+    Object create()
+    {
+        if (flags & 8 && !defaultConstructor)
+            return null;
+        Object o = _d_newclass(this);
+        if (flags & 8 && defaultConstructor)
+        {
+            Object delegate() ctor;
+            ctor.ptr = cast(void*)o;
+            ctor.funcptr = cast(Object function())defaultConstructor;
+            ctor();
+            //defaultConstructor(o);
+        }
+        return o;
+    }
+
+    /**
+     * Search for all members with the name 'name'.
+     * If name[] is null, return all members.
+     */
+    const(MemberInfo[]) getMembers(in char[] name)
+    {
+        if (flags & 16 && xgetMembers)
+            return xgetMembers(name);
+        return null;
+    }
+}
+
+/**
+ * Array of pairs giving the offset and type information for each
+ * member in an aggregate.
+ */
+struct OffsetTypeInfo
+{
+    size_t   offset;    /// Offset of member from start of object
+    TypeInfo ti;        /// TypeInfo for this member
+}
+
+/**
+ * Runtime type information about a type.
+ * Can be retrieved for any type using a
+ * <a href="../expression.html#typeidexpression">TypeidExpression</a>.
+ */
+class TypeInfo
+{
+    override hash_t toHash()
+    {
+        hash_t hash;
+
+        foreach (char c; this.toString())
+            hash = hash * 9 + c;
+        return hash;
+    }
+
+    override int opCmp(Object o)
+    {
+        if (this is o)
+            return 0;
+        TypeInfo ti = cast(TypeInfo)o;
+        if (ti is null)
+            return 1;
+        return dstrcmp(this.toString(), ti.toString());
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        /* TypeInfo instances are singletons, but duplicates can exist
+         * across DLL's. Therefore, comparing for a name match is
+         * sufficient.
+         */
+        if (this is o)
+            return true;
+        TypeInfo ti = cast(TypeInfo)o;
+        return ti && this.toString() == ti.toString();
+    }
+
+    /// Returns a hash of the instance of a type.
+    hash_t getHash(in void* p) { return cast(hash_t)p; }
+
+    /// Compares two instances for equality.
+    equals_t equals(in void* p1, in void* p2) { return p1 == p2; }
+
+    /// Compares two instances for &lt;, ==, or &gt;.
+    int compare(in void* p1, in void* p2) { return 0; }
+
+    /// Returns size of the type.
+    size_t tsize() { return 0; }
+
+    /// Swaps two instances of the type.
+    void swap(void* p1, void* p2)
+    {
+        size_t n = tsize();
+        for (size_t i = 0; i < n; i++)
+        {
+            byte t = (cast(byte *)p1)[i];
+            (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
+            (cast(byte*)p2)[i] = t;
+        }
+    }
+
+    /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
+    /// null if none.
+    TypeInfo next() { return null; }
+
+    /// Return default initializer, null if default initialize to 0
+    void[] init() { return null; }
+
+    /// Get flags for type: 1 means GC should scan for pointers
+    uint flags() { return 0; }
+
+    /// Get type information on the contents of the type; null if not available
+    OffsetTypeInfo[] offTi() { return null; }
+    /// Run the destructor on the object and all its sub-objects
+    void destroy(void* p) {}
+    /// Run the postblit on the object and all its sub-objects
+    void postblit(void* p) {}
+}
+
+class TypeInfo_Typedef : TypeInfo
+{
+    override string toString() { return name; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Typedef c;
+        return this is o ||
+               ((c = cast(TypeInfo_Typedef)o) !is null &&
+                this.name == c.name &&
+                this.base == c.base);
+    }
+
+    override hash_t getHash(in void* p) { return base.getHash(p); }
+    override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); }
+    override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); }
+    override size_t tsize() { return base.tsize(); }
+    override void swap(void* p1, void* p2) { return base.swap(p1, p2); }
+
+    override TypeInfo next() { return base.next(); }
+    override uint flags() { return base.flags(); }
+    override void[] init() { return m_init.length ? m_init : base.init(); }
+
+    TypeInfo base;
+    string   name;
+    void[]   m_init;
+}
+
+class TypeInfo_Enum : TypeInfo_Typedef
+{
+
+}
+
+class TypeInfo_Pointer : TypeInfo
+{
+    override string toString() { return m_next.toString() ~ "*"; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Pointer c;
+        return this is o ||
+                ((c = cast(TypeInfo_Pointer)o) !is null &&
+                 this.m_next == c.m_next);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        return cast(hash_t)*cast(void**)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(void**)p1 == *cast(void**)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        if (*cast(void**)p1 < *cast(void**)p2)
+            return -1;
+        else if (*cast(void**)p1 > *cast(void**)p2)
+            return 1;
+        else
+            return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (void*).sizeof;
+    }
+
+    override void swap(void* p1, void* p2)
+    {
+        void* tmp = *cast(void**)p1;
+        *cast(void**)p1 = *cast(void**)p2;
+        *cast(void**)p2 = tmp;
+    }
+
+    override TypeInfo next() { return m_next; }
+    override uint flags() { return 1; }
+
+    TypeInfo m_next;
+}
+
+class TypeInfo_Array : TypeInfo
+{
+    override string toString() { return value.toString() ~ "[]"; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Array c;
+        return this is o ||
+               ((c = cast(TypeInfo_Array)o) !is null &&
+                this.value == c.value);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        size_t sz = value.tsize();
+        hash_t hash = 0;
+        void[] a = *cast(void[]*)p;
+        for (size_t i = 0; i < a.length; i++)
+            hash += value.getHash(a.ptr + i * sz) * 11;
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        void[] a1 = *cast(void[]*)p1;
+        void[] a2 = *cast(void[]*)p2;
+        if (a1.length != a2.length)
+            return false;
+        size_t sz = value.tsize();
+        for (size_t i = 0; i < a1.length; i++)
+        {
+            if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        void[] a1 = *cast(void[]*)p1;
+        void[] a2 = *cast(void[]*)p2;
+        size_t sz = value.tsize();
+        size_t len = a1.length;
+
+        if (a2.length < len)
+            len = a2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
+            if (result)
+                return result;
+        }
+        return cast(int)a1.length - cast(int)a2.length;
+    }
+
+    override size_t tsize()
+    {
+        return (void[]).sizeof;
+    }
+
+    override void swap(void* p1, void* p2)
+    {
+        void[] tmp = *cast(void[]*)p1;
+        *cast(void[]*)p1 = *cast(void[]*)p2;
+        *cast(void[]*)p2 = tmp;
+    }
+
+    TypeInfo value;
+
+    override TypeInfo next()
+    {
+        return value;
+    }
+
+    override uint flags() { return 1; }
+}
+
+class TypeInfo_StaticArray : TypeInfo
+{
+    override string toString()
+    {
+        char[10] tmp = void;
+        return cast(string)(value.toString() ~ "[" ~ tmp.intToString(len) ~ "]");
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_StaticArray c;
+        return this is o ||
+               ((c = cast(TypeInfo_StaticArray)o) !is null &&
+                this.len == c.len &&
+                this.value == c.value);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        size_t sz = value.tsize();
+        hash_t hash = 0;
+        for (size_t i = 0; i < len; i++)
+            hash += value.getHash(p + i * sz);
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        size_t sz = value.tsize();
+
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!value.equals(p1 + u * sz, p2 + u * sz))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        size_t sz = value.tsize();
+
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = value.compare(p1 + u * sz, p2 + u * sz);
+            if (result)
+                return result;
+        }
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return len * value.tsize();
+    }
+
+    override void swap(void* p1, void* p2)
+    {
+        void* tmp;
+        size_t sz = value.tsize();
+        ubyte[16] buffer;
+        void* pbuffer;
+
+        if (sz < buffer.sizeof)
+            tmp = buffer.ptr;
+        else
+            tmp = pbuffer = (new void[sz]).ptr;
+
+        for (size_t u = 0; u < len; u += sz)
+        {   size_t o = u * sz;
+            memcpy(tmp, p1 + o, sz);
+            memcpy(p1 + o, p2 + o, sz);
+            memcpy(p2 + o, tmp, sz);
+        }
+        if (pbuffer)
+            delete pbuffer;
+    }
+
+    override void[] init() { return value.init(); }
+    override TypeInfo next() { return value; }
+    override uint flags() { return value.flags(); }
+
+    override void destroy(void* p)
+    {
+        auto sz = value.tsize();
+        p += sz * len;
+        foreach (i; 0 .. len)
+        {
+            p -= sz;
+            value.destroy(p);
+        }
+    }
+
+    override void postblit(void* p)
+    {
+        auto sz = value.tsize();
+        foreach (i; 0 .. len)
+        {
+            value.postblit(p);
+            p += sz;
+        }
+    }
+
+    TypeInfo value;
+    size_t   len;
+}
+
+class TypeInfo_AssociativeArray : TypeInfo
+{
+    override string toString()
+    {
+        return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]");
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_AssociativeArray c;
+        return this is o ||
+                ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
+                 this.key == c.key &&
+                 this.value == c.value);
+    }
+
+    // BUG: need to add the rest of the functions
+
+    override size_t tsize()
+    {
+        return (char[int]).sizeof;
+    }
+
+    override TypeInfo next() { return value; }
+    override uint flags() { return 1; }
+
+    TypeInfo value;
+    TypeInfo key;
+}
+
+class TypeInfo_Function : TypeInfo
+{
+    override string toString()
+    {
+        return cast(string)(next.toString() ~ "()");
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Function c;
+        return this is o ||
+                ((c = cast(TypeInfo_Function)o) !is null &&
+                 this.next == c.next);
+    }
+
+    // BUG: need to add the rest of the functions
+
+    override size_t tsize()
+    {
+        return 0;       // no size for functions
+    }
+
+    TypeInfo next;
+}
+
+class TypeInfo_Delegate : TypeInfo
+{
+    override string toString()
+    {
+        return cast(string)(next.toString() ~ " delegate()");
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Delegate c;
+        return this is o ||
+                ((c = cast(TypeInfo_Delegate)o) !is null &&
+                 this.next == c.next);
+    }
+
+    // BUG: need to add the rest of the functions
+
+    override size_t tsize()
+    {
+        alias int delegate() dg;
+        return dg.sizeof;
+    }
+
+    override uint flags() { return 1; }
+
+    TypeInfo next;
+}
+
+class TypeInfo_Class : TypeInfo
+{
+    override string toString() { return info.name; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Class c;
+        return this is o ||
+                ((c = cast(TypeInfo_Class)o) !is null &&
+                 this.info.name == c.classinfo.name);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        Object o = *cast(Object*)p;
+        return o ? o.toHash() : 0;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        Object o1 = *cast(Object*)p1;
+        Object o2 = *cast(Object*)p2;
+
+        return (o1 is o2) || (o1 && o1.opEquals(o2));
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        Object o1 = *cast(Object*)p1;
+        Object o2 = *cast(Object*)p2;
+        int c = 0;
+
+        // Regard null references as always being "less than"
+        if (o1 !is o2)
+        {
+            if (o1)
+            {
+                if (!o2)
+                    c = 1;
+                else
+                    c = o1.opCmp(o2);
+            }
+            else
+                c = -1;
+        }
+        return c;
+    }
+
+    override size_t tsize()
+    {
+        return Object.sizeof;
+    }
+
+    override uint flags() { return 1; }
+
+    override OffsetTypeInfo[] offTi()
+    {
+        return (info.flags & 4) ? info.offTi : null;
+    }
+
+    ClassInfo info;
+}
+
+class TypeInfo_Interface : TypeInfo
+{
+    override string toString() { return info.name; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Interface c;
+        return this is o ||
+                ((c = cast(TypeInfo_Interface)o) !is null &&
+                 this.info.name == c.classinfo.name);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        Interface* pi = **cast(Interface ***)*cast(void**)p;
+        Object o = cast(Object)(*cast(void**)p - pi.offset);
+        assert(o);
+        return o.toHash();
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        Interface* pi = **cast(Interface ***)*cast(void**)p1;
+        Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
+        pi = **cast(Interface ***)*cast(void**)p2;
+        Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
+
+        return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        Interface* pi = **cast(Interface ***)*cast(void**)p1;
+        Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
+        pi = **cast(Interface ***)*cast(void**)p2;
+        Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
+        int c = 0;
+
+        // Regard null references as always being "less than"
+        if (o1 != o2)
+        {
+            if (o1)
+            {
+                if (!o2)
+                    c = 1;
+                else
+                    c = o1.opCmp(o2);
+            }
+            else
+                c = -1;
+        }
+        return c;
+    }
+
+    override size_t tsize()
+    {
+        return Object.sizeof;
+    }
+
+    override uint flags() { return 1; }
+
+    ClassInfo info;
+}
+
+class TypeInfo_Struct : TypeInfo
+{
+    override string toString() { return name; }
+
+    override equals_t opEquals(Object o)
+    {
+        TypeInfo_Struct s;
+        return this is o ||
+                ((s = cast(TypeInfo_Struct)o) !is null &&
+                 this.name == s.name &&
+                 this.init.length == s.init.length);
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        assert(p);
+        if (xtoHash)
+        {
+            debug(PRINTF) printf("getHash() using xtoHash\n");
+            return (*xtoHash)(p);
+        }
+        else
+        {
+            hash_t h;
+            debug(PRINTF) printf("getHash() using default hash\n");
+            // A sorry hash algorithm.
+            // Should use the one for strings.
+            // BUG: relies on the GC not moving objects
+            auto q = cast(const(ubyte)*)p;
+            for (size_t i = 0; i < init.length; i++)
+            {
+                h = h * 9 + *q;
+                q++;
+            }
+            return h;
+        }
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        if (p1 == p2)
+            return true;
+        else if (!p1 || !p2)
+            return false;
+        else if (xopEquals)
+            return (*xopEquals)(p1, p2);
+        else
+            // BUG: relies on the GC not moving objects
+            return memcmp(p1, p2, init.length) == 0;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        // Regard null references as always being "less than"
+        if (p1 != p2)
+        {
+            if (p1)
+            {
+                if (!p2)
+                    return true;
+                else if (xopCmp)
+                    return (*xopCmp)(p2, p1);
+                else
+                    // BUG: relies on the GC not moving objects
+                    return memcmp(p1, p2, init.length);
+            }
+            else
+                return -1;
+        }
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return init.length;
+    }
+
+    override void[] init() { return m_init; }
+
+    override uint flags() { return m_flags; }
+
+    override void destroy(void* p)
+    {
+        if (xdtor)
+            (*xdtor)(p);
+    }
+
+    override void postblit(void* p)
+    {
+        if (xpostblit)
+            (*xpostblit)(p);
+    }
+
+    string name;
+    void[] m_init;      // initializer; init.ptr == null if 0 initialize
+
+    hash_t   function(in void*)           xtoHash;
+    equals_t function(in void*, in void*) xopEquals;
+    int      function(in void*, in void*) xopCmp;
+    char[]   function(in void*)           xtoString;
+
+    uint m_flags;
+
+    const(MemberInfo[]) function(in char[]) xgetMembers;
+    void function(void*)                    xdtor;
+    void function(void*)                    xpostblit;
+}
+
+class TypeInfo_Tuple : TypeInfo
+{
+    TypeInfo[] elements;
+
+    override string toString()
+    {
+        string s = "(";
+        foreach (i, element; elements)
+        {
+            if (i)
+                s ~= ',';
+            s ~= element.toString();
+        }
+        s ~= ")";
+        return s;
+    }
+
+    override equals_t opEquals(Object o)
+    {
+        if (this is o)
+            return true;
+
+        auto t = cast(TypeInfo_Tuple)o;
+        if (t && elements.length == t.elements.length)
+        {
+            for (size_t i = 0; i < elements.length; i++)
+            {
+                if (elements[i] != t.elements[i])
+                    return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    override hash_t getHash(in void* p)
+    {
+        assert(0);
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        assert(0);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        assert(0);
+    }
+
+    override size_t tsize()
+    {
+        assert(0);
+    }
+
+    override void swap(void* p1, void* p2)
+    {
+        assert(0);
+    }
+
+    override void destroy(void* p)
+    {
+        assert(0);
+    }
+
+    override void postblit(void* p)
+    {
+        assert(0);
+    }
+}
+
+class TypeInfo_Const : TypeInfo
+{
+    override string toString()
+    {
+        return cast(string) ("const(" ~ base.toString() ~ ")");
+    }
+
+    override equals_t opEquals(Object o) { return base.opEquals(o); }
+    override hash_t getHash(in void *p) { return base.getHash(p); }
+    override equals_t equals(in void *p1, in void *p2) { return base.equals(p1, p2); }
+    override int compare(in void *p1, in void *p2) { return base.compare(p1, p2); }
+    override size_t tsize() { return base.tsize(); }
+    override void swap(void *p1, void *p2) { return base.swap(p1, p2); }
+
+    override TypeInfo next() { return base.next(); }
+    override uint flags() { return base.flags(); }
+    override void[] init() { return base.init(); }
+
+    TypeInfo base;
+}
+
+class TypeInfo_Invariant : TypeInfo_Const
+{
+    override string toString()
+    {
+        return cast(string) ("immutable(" ~ base.toString() ~ ")");
+    }
+}
+
+class TypeInfo_Shared : TypeInfo_Const
+{
+    override string toString()
+    {
+        return cast(string) ("shared(" ~ base.toString() ~ ")");
+    }
+}
+
+abstract class MemberInfo
+{
+    string name();
+}
+
+class MemberInfo_field : MemberInfo
+{
+    this(string name, TypeInfo ti, size_t offset)
+    {
+        m_name = name;
+        m_typeinfo = ti;
+        m_offset = offset;
+    }
+
+    override string name() { return m_name; }
+    TypeInfo typeInfo() { return m_typeinfo; }
+    size_t offset() { return m_offset; }
+
+    string   m_name;
+    TypeInfo m_typeinfo;
+    size_t   m_offset;
+}
+
+class MemberInfo_function : MemberInfo
+{
+    this(string name, TypeInfo ti, void* fp, uint flags)
+    {
+        m_name = name;
+        m_typeinfo = ti;
+        m_fp = fp;
+        m_flags = flags;
+    }
+
+    override string name() { return m_name; }
+    TypeInfo typeInfo() { return m_typeinfo; }
+    void* fp() { return m_fp; }
+    uint flags() { return m_flags; }
+
+    string   m_name;
+    TypeInfo m_typeinfo;
+    void*    m_fp;
+    uint     m_flags;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Throwable
+///////////////////////////////////////////////////////////////////////////////
+
+
+class Throwable : Object
+{
+    interface TraceInfo
+    {
+        int opApply(int delegate(inout char[]));
+    }
+
+    string      msg;
+    string      file;
+    size_t      line;
+    TraceInfo   info;
+    Throwable   next;
+
+    this(string msg, Throwable next = null)
+    {
+        this.msg = msg;
+        this.next = next;
+        this.info = traceContext();
+    }
+
+    this(string msg, string file, size_t line, Throwable next = null)
+    {
+        this(msg, next);
+        this.file = file;
+        this.line = line;
+        this.info = traceContext();
+    }
+
+    override string toString()
+    {
+        char[10] tmp = void;
+        char[]   buf;
+
+        for (Throwable e = this; e !is null; e = e.next)
+        {
+            if (e.file)
+            {
+               buf ~= e.classinfo.name ~ "@" ~ e.file ~ "(" ~ tmp.intToString(e.line) ~ "): " ~ e.msg;
+            }
+            else
+            {
+               buf ~= e.classinfo.name ~ ": " ~ e.msg;
+            }
+            if (e.info)
+            {
+                buf ~= "\n----------------";
+                foreach (t; e.info)
+                    buf ~= "\n" ~ t;
+            }
+            if (e.next)
+                buf ~= "\n";
+        }
+        return cast(string) buf;
+    }
+}
+
+
+alias Throwable.TraceInfo function(void* ptr = null) TraceHandler;
+private __gshared TraceHandler traceHandler = null;
+
+
+/**
+ * Overrides the default trace hander with a user-supplied version.
+ *
+ * Params:
+ *  h = The new trace handler.  Set to null to use the default handler.
+ */
+extern (C) void  rt_setTraceHandler(TraceHandler h)
+{
+    traceHandler = h;
+}
+
+
+/**
+ * This function will be called when an exception is constructed.  The
+ * user-supplied trace handler will be called if one has been supplied,
+ * otherwise no trace will be generated.
+ *
+ * Params:
+ *  ptr = A pointer to the location from which to generate the trace, or null
+ *        if the trace should be generated from within the trace handler
+ *        itself.
+ *
+ * Returns:
+ *  An object describing the current calling context or null if no handler is
+ *  supplied.
+ */
+Throwable.TraceInfo traceContext(void* ptr = null)
+{
+    if (traceHandler is null)
+        return null;
+    return traceHandler(ptr);
+}
+
+
+class Exception : Throwable
+{
+    this(string msg, Throwable next = null)
+    {
+        super(msg, next);
+    }
+
+    this(string msg, string file, size_t line, Throwable next = null)
+    {
+        super(msg, file, line, next);
+    }
+}
+
+
+class Error : Throwable
+{
+    this(string msg, Throwable next = null)
+    {
+        super(msg, next);
+    }
+
+    this(string msg, string file, size_t line, Throwable next = null)
+    {
+        super(msg, file, line, next);
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// ModuleInfo
+///////////////////////////////////////////////////////////////////////////////
+
+
+enum
+{
+    MIctorstart  = 1,   // we've started constructing it
+    MIctordone   = 2,   // finished construction
+    MIstandalone = 4,   // module ctor does not depend on other module
+                        // ctors being done first
+    MIhasictor   = 8,   // has ictor member
+}
+
+
+class ModuleInfo
+{
+    string          name;
+    ModuleInfo[]    importedModules;
+    ClassInfo[]     localClasses;
+    uint            flags;
+
+    void function() ctor;       // module static constructor (order dependent)
+    void function() dtor;       // module static destructor
+    void function() unitTest;   // module unit tests
+
+    void* xgetMembers;          // module getMembers() function
+
+    void function() ictor;      // module static constructor (order independent)
+
+    void*[4] reserved;		// for future expansion
+
+    static int opApply(int delegate(inout ModuleInfo) dg)
+    {
+        int ret = 0;
+
+        foreach (m; _moduleinfo_array)
+        {
+            ret = dg(m);
+            if (ret)
+                break;
+        }
+        return ret;
+    }
+}
+
+
+// Windows: this gets initialized by minit.asm
+// Posix: this gets initialized in _moduleCtor()
+extern (C) __gshared ModuleInfo[] _moduleinfo_array;
+
+
+version (linux)
+{
+    // This linked list is created by a compiler generated function inserted
+    // into the .ctor list by the compiler.
+    struct ModuleReference
+    {
+        ModuleReference* next;
+        ModuleInfo       mod;
+    }
+
+    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
+}
+
+version (FreeBSD)
+{
+    // This linked list is created by a compiler generated function inserted
+    // into the .ctor list by the compiler.
+    struct ModuleReference
+    {
+        ModuleReference* next;
+        ModuleInfo       mod;
+    }
+
+    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
+}
+
+version (Solaris)
+{
+    // This linked list is created by a compiler generated function inserted
+    // into the .ctor list by the compiler.
+    struct ModuleReference
+    {
+        ModuleReference* next;
+        ModuleInfo       mod;
+    }
+
+    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
+}
+
+version (OSX)
+{
+    extern (C)
+    {
+        extern __gshared void* _minfo_beg;
+        extern __gshared void* _minfo_end;
+    }
+}
+
+__gshared ModuleInfo[] _moduleinfo_dtors;
+__gshared uint         _moduleinfo_dtors_i;
+
+// Register termination function pointers
+extern (C) int _fatexit(void*);
+
+/**
+ * Initialize the modules.
+ */
+
+extern (C) void _moduleCtor()
+{
+    debug(PRINTF) printf("_moduleCtor()\n");
+    version (linux)
+    {
+        int len = 0;
+        ModuleReference *mr;
+
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+            len++;
+        _moduleinfo_array = new ModuleInfo[len];
+        len = 0;
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+        {   _moduleinfo_array[len] = mr.mod;
+            len++;
+        }
+    }
+
+    version (FreeBSD)
+    {
+        int len = 0;
+        ModuleReference *mr;
+
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+            len++;
+        _moduleinfo_array = new ModuleInfo[len];
+        len = 0;
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+        {   _moduleinfo_array[len] = mr.mod;
+            len++;
+        }
+    }
+
+    version (Solaris)
+    {
+        int len = 0;
+        ModuleReference *mr;
+
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+            len++;
+        _moduleinfo_array = new ModuleInfo[len];
+        len = 0;
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+        {   _moduleinfo_array[len] = mr.mod;
+            len++;
+        }
+    }
+
+    version (OSX)
+    {
+        /* The ModuleInfo references are stored in the special segment
+         * __minfodata, which is bracketed by the segments __minfo_beg
+         * and __minfo_end. The variables _minfo_beg and _minfo_end
+         * are of zero size and are in the two bracketing segments,
+         * respectively.
+         */
+         size_t length = cast(ModuleInfo*)&_minfo_end - cast(ModuleInfo*)&_minfo_beg;
+         _moduleinfo_array = (cast(ModuleInfo*)&_minfo_beg)[0 .. length];
+         debug printf("moduleinfo: ptr = %p, length = %d\n", _moduleinfo_array.ptr, _moduleinfo_array.length);
+
+         debug foreach (m; _moduleinfo_array)
+         {
+             //printf("\t%p\n", m);
+             printf("\t%.*s\n", m.name);
+         }
+    }    
+
+    version (Windows)
+    {
+        // Ensure module destructors also get called on program termination
+        //_fatexit(&_STD_moduleDtor);
+    }
+
+    _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
+    debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors);
+    _moduleIndependentCtors();
+    _moduleCtor2(_moduleinfo_array, 0);
+}
+
+extern (C) void _moduleIndependentCtors()
+{
+    debug(PRINTF) printf("_moduleIndependentCtors()\n");
+    foreach (m; _moduleinfo_array)
+    {
+        if (m && m.flags & MIhasictor && m.ictor)
+        {
+            (*m.ictor)();
+        }
+    }
+}
+
+void _moduleCtor2(ModuleInfo[] mi, int skip)
+{
+    debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
+    for (uint i = 0; i < mi.length; i++)
+    {
+        ModuleInfo m = mi[i];
+
+        debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
+        if (!m)
+            continue;
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
+        if (m.flags & MIctordone)
+            continue;
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
+
+        if (m.ctor || m.dtor)
+        {
+            if (m.flags & MIctorstart)
+            {   if (skip || m.flags & MIstandalone)
+                    continue;
+                    throw new Exception("Cyclic dependency in module " ~ m.name);
+            }
+
+            m.flags |= MIctorstart;
+            _moduleCtor2(m.importedModules, 0);
+            if (m.ctor)
+                (*m.ctor)();
+            m.flags &= ~MIctorstart;
+            m.flags |= MIctordone;
+
+            // Now that construction is done, register the destructor
+            //printf("\tadding module dtor x%x\n", m);
+            assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
+            _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
+        }
+        else
+        {
+            m.flags |= MIctordone;
+            _moduleCtor2(m.importedModules, 1);
+        }
+    }
+}
+
+/**
+ * Destruct the modules.
+ */
+
+// Starting the name with "_STD" means under Posix a pointer to the
+// function gets put in the .dtors segment.
+
+extern (C) void _moduleDtor()
+{
+    debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
+
+    for (uint i = _moduleinfo_dtors_i; i-- != 0;)
+    {
+        ModuleInfo m = _moduleinfo_dtors[i];
+
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
+        if (m.dtor)
+        {
+            (*m.dtor)();
+        }
+    }
+    debug(PRINTF) printf("_moduleDtor() done\n");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Monitor
+///////////////////////////////////////////////////////////////////////////////
+
+alias Object.Monitor        IMonitor;
+alias void delegate(Object) DEvent;
+
+// NOTE: The dtor callback feature is only supported for monitors that are not
+//       supplied by the user.  The assumption is that any object with a user-
+//       supplied monitor may have special storage or lifetime requirements and
+//       that as a result, storing references to local objects within Monitor
+//       may not be safe or desirable.  Thus, devt is only valid if impl is
+//       null.
+struct Monitor
+{
+    IMonitor impl;
+    /* internal */
+    DEvent[] devt;
+    /* stuff */
+}
+
+Monitor* getMonitor(Object h)
+{
+    return cast(Monitor*) (cast(void**) h)[1];
+}
+
+void setMonitor(Object h, Monitor* m)
+{
+    (cast(void**) h)[1] = m;
+}
+
+extern (C) void _d_monitor_create(Object);
+extern (C) void _d_monitor_destroy(Object);
+extern (C) void _d_monitor_lock(Object);
+extern (C) int  _d_monitor_unlock(Object);
+
+extern (C) void _d_monitordelete(Object h, bool det)
+{
+    Monitor* m = getMonitor(h);
+
+    if (m !is null)
+    {
+        IMonitor i = m.impl;
+        if (i is null)
+        {
+            _d_monitor_devt(m, h);
+            _d_monitor_destroy(h);
+            setMonitor(h, null);
+            return;
+        }
+        if (det && (cast(void*) i) !is (cast(void*) h))
+            delete i;
+        setMonitor(h, null);
+    }
+}
+
+extern (C) void _d_monitorenter(Object h)
+{
+    Monitor* m = getMonitor(h);
+
+    if (m is null)
+    {
+        _d_monitor_create(h);
+        m = getMonitor(h);
+    }
+
+    IMonitor i = m.impl;
+
+    if (i is null)
+    {
+        _d_monitor_lock(h);
+        return;
+    }
+    i.lock();
+}
+
+extern (C) void _d_monitorexit(Object h)
+{
+    Monitor* m = getMonitor(h);
+    IMonitor i = m.impl;
+
+    if (i is null)
+    {
+        _d_monitor_unlock(h);
+        return;
+    }
+    i.unlock();
+}
+
+extern (C) void _d_monitor_devt(Monitor* m, Object h)
+{
+    if (m.devt.length)
+    {
+        DEvent[] devt;
+
+        synchronized (h)
+        {
+            devt = m.devt;
+            m.devt = null;
+        }
+        foreach (v; devt)
+        {
+            if (v)
+                v(h);
+        }
+        free(devt.ptr);
+    }
+}
+
+extern (C) void rt_attachDisposeEvent(Object h, DEvent e)
+{
+    synchronized (h)
+    {
+        Monitor* m = getMonitor(h);
+        assert(m.impl is null);
+
+        foreach (inout v; m.devt)
+        {
+            if (v is null || v == e)
+            {
+                v = e;
+                return;
+            }
+        }
+
+        auto len = m.devt.length + 4; // grow by 4 elements
+        auto pos = m.devt.length;     // insert position
+        auto p = realloc(m.devt.ptr, DEvent.sizeof * len);
+        if (!p)
+            onOutOfMemoryError();
+        m.devt = (cast(DEvent*)p)[0 .. len];
+        m.devt[pos+1 .. len] = null;
+        m.devt[pos] = e;
+    }
+}
+
+extern (C) void rt_detachDisposeEvent(Object h, DEvent e)
+{
+    synchronized (h)
+    {
+        Monitor* m = getMonitor(h);
+        assert(m.impl is null);
+
+        foreach (p, v; m.devt)
+        {
+            if (v == e)
+            {
+                memmove(&m.devt[p],
+                        &m.devt[p+1],
+                        (m.devt.length - p - 1) * DEvent.sizeof);
+                m.devt[$ - 1] = null;
+                return;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/invariant.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,35 @@
+/**
+ * Implementation of invariant support routines.
+ *
+ * Copyright: Copyright Digital Mars 2007 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2007 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+
+/**
+ *
+ */
+void _d_invariant(Object o)
+{   ClassInfo c;
+
+    //printf("__d_invariant(%p)\n", o);
+
+    // BUG: needs to be filename/line of caller, not library routine
+    assert(o !is null); // just do null check, not invariant check
+
+    c = o.classinfo;
+    do
+    {
+        if (c.classInvariant)
+        {
+            (*c.classInvariant)(o);
+        }
+        c = c.base;
+    } while (c);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/invariant_.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,32 @@
+/**
+ * Implementation of invariant support routines.
+ *
+ * Copyright: Copyright Digital Mars 2007 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2007 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.invariant_;
+
+extern (C) void _d_invariant(Object o)
+{   ClassInfo c;
+
+    //printf("__d_invariant(%p)\n", o);
+
+    // BUG: needs to be filename/line of caller, not library routine
+    assert(o !is null); // just do null check, not invariant check
+
+    c = o.classinfo;
+    do
+    {
+        if (c.classInvariant)
+        {
+            (*c.classInvariant)(o);
+        }
+        c = c.base;
+    } while (c);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/lifetime.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,1073 @@
+/**
+ * This module contains all functions related to an object's lifetime:
+ * allocation, resizing, deallocation, and finalization.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.lifetime;
+
+
+private
+{
+    import core.stdc.stdlib;
+    import core.stdc.string;
+    import core.stdc.stdarg;
+    debug(PRINTF) import core.stdc.stdio;
+}
+
+
+private
+{
+    enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001,
+        NO_SCAN  = 0b0000_0010,
+        NO_MOVE  = 0b0000_0100,
+        ALL_BITS = 0b1111_1111
+    }
+
+    struct BlkInfo
+    {
+        void*  base;
+        size_t size;
+        uint   attr;
+    }
+
+    extern (C) uint gc_getAttr( void* p );
+    extern (C) uint gc_setAttr( void* p, uint a );
+    extern (C) uint gc_clrAttr( void* p, uint a );
+
+    extern (C) void*  gc_malloc( size_t sz, uint ba = 0 );
+    extern (C) void*  gc_calloc( size_t sz, uint ba = 0 );
+    extern (C) size_t gc_extend( void* p, size_t mx, size_t sz );
+    extern (C) void   gc_free( void* p );
+
+    extern (C) void*   gc_addrOf( void* p );
+    extern (C) size_t  gc_sizeOf( void* p );
+    extern (C) BlkInfo gc_query( void* p );
+
+    extern (C) void onFinalizeError( ClassInfo c, Throwable e );
+    extern (C) void onOutOfMemoryError();
+
+    extern (C) void _d_monitordelete(Object h, bool det = true);
+
+    enum
+    {
+        PAGESIZE = 4096
+    }
+
+    alias bool function(Object) CollectHandler;
+    __gshared CollectHandler collectHandler = null;
+}
+
+
+/**
+ *
+ */
+extern (C) void* _d_allocmemory(size_t sz)
+{
+    return gc_malloc(sz);
+}
+
+
+/**
+ *
+ */
+extern (C) Object _d_newclass(ClassInfo ci)
+{
+    void* p;
+
+    debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name);
+    if (ci.flags & 1) // if COM object
+    {   /* COM objects are not garbage collected, they are reference counted
+         * using AddRef() and Release().  They get free'd by C's free()
+         * function called by Release() when Release()'s reference count goes
+         * to zero.
+     */
+        p = malloc(ci.init.length);
+        if (!p)
+            onOutOfMemoryError();
+    }
+    else
+    {
+        p = gc_malloc(ci.init.length,
+                      BlkAttr.FINALIZE | (ci.flags & 2 ? BlkAttr.NO_SCAN : 0));
+        debug(PRINTF) printf(" p = %p\n", p);
+    }
+
+    debug(PRINTF)
+    {
+        printf("p = %p\n", p);
+        printf("ci = %p, ci.init = %p, len = %d\n", ci, ci.init, ci.init.length);
+        printf("vptr = %p\n", *cast(void**) ci.init);
+        printf("vtbl[0] = %p\n", (*cast(void***) ci.init)[0]);
+        printf("vtbl[1] = %p\n", (*cast(void***) ci.init)[1]);
+        printf("init[0] = %x\n", (cast(uint*) ci.init)[0]);
+        printf("init[1] = %x\n", (cast(uint*) ci.init)[1]);
+        printf("init[2] = %x\n", (cast(uint*) ci.init)[2]);
+        printf("init[3] = %x\n", (cast(uint*) ci.init)[3]);
+        printf("init[4] = %x\n", (cast(uint*) ci.init)[4]);
+    }
+
+    // initialize it
+    (cast(byte*) p)[0 .. ci.init.length] = ci.init[];
+
+    debug(PRINTF) printf("initialization done\n");
+    return cast(Object) p;
+}
+
+
+/**
+ *
+ */
+extern (C) void _d_delinterface(void** p)
+{
+    if (*p)
+    {
+        Interface* pi = **cast(Interface ***)*p;
+        Object     o  = cast(Object)(*p - pi.offset);
+
+        _d_delclass(&o);
+        *p = null;
+    }
+}
+
+
+// used for deletion
+private extern (D) alias void (*fp_t)(Object);
+
+
+/**
+ *
+ */
+extern (C) void _d_delclass(Object* p)
+{
+    if (*p)
+    {
+        debug(PRINTF) printf("_d_delclass(%p)\n", *p);
+
+        ClassInfo **pc = cast(ClassInfo **)*p;
+        if (*pc)
+        {
+            ClassInfo c = **pc;
+
+            rt_finalize(cast(void*) *p);
+
+            if (c.deallocator)
+            {
+                fp_t fp = cast(fp_t)c.deallocator;
+                (*fp)(*p); // call deallocator
+                *p = null;
+                return;
+            }
+        }
+        else
+        {
+            rt_finalize(cast(void*) *p);
+        }
+        gc_free(cast(void*) *p);
+        *p = null;
+    }
+}
+
+
+/**
+ * Allocate a new array of length elements.
+ * ti is the type of the resulting array, or pointer to element.
+ * (For when the array is initialized to 0)
+ */
+extern (C) ulong _d_newarrayT(TypeInfo ti, size_t length)
+{
+    void* p;
+    ulong result;
+    auto size = ti.next.tsize();                // array element size
+
+    debug(PRINTF) printf("_d_newarrayT(length = x%x, size = %d)\n", length, size);
+    if (length == 0 || size == 0)
+        result = 0;
+    else
+    {
+        version (D_InlineAsm_X86)
+        {
+            asm
+            {
+                mov     EAX,size        ;
+                mul     EAX,length      ;
+                mov     size,EAX        ;
+                jc      Loverflow       ;
+            }
+        }
+        else
+            size *= length;
+        p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        debug(PRINTF) printf(" p = %p\n", p);
+        memset(p, 0, size);
+        result = cast(ulong)length + (cast(ulong)cast(uint)p << 32);
+    }
+    return result;
+
+Loverflow:
+    onOutOfMemoryError();
+}
+
+/**
+ * For when the array has a non-zero initializer.
+ */
+extern (C) ulong _d_newarrayiT(TypeInfo ti, size_t length)
+{
+    ulong result;
+    auto size = ti.next.tsize();                // array element size
+
+    debug(PRINTF) printf("_d_newarrayiT(length = %d, size = %d)\n", length, size);
+
+    if (length == 0 || size == 0)
+        result = 0;
+    else
+    {
+        auto initializer = ti.next.init();
+        auto isize = initializer.length;
+        auto q = initializer.ptr;
+        version (D_InlineAsm_X86)
+        {
+            asm
+            {
+                mov     EAX,size        ;
+                mul     EAX,length      ;
+                mov     size,EAX        ;
+                jc      Loverflow       ;
+            }
+        }
+        else
+            size *= length;
+        auto p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        debug(PRINTF) printf(" p = %p\n", p);
+        if (isize == 1)
+            memset(p, *cast(ubyte*)q, size);
+        else if (isize == int.sizeof)
+        {
+            int init = *cast(int*)q;
+            size /= int.sizeof;
+            for (size_t u = 0; u < size; u++)
+            {
+                (cast(int*)p)[u] = init;
+            }
+        }
+        else
+        {
+            for (size_t u = 0; u < size; u += isize)
+            {
+                memcpy(p + u, q, isize);
+            }
+        }
+        va_end(q);
+        result = cast(ulong)length + (cast(ulong)cast(uint)p << 32);
+    }
+    return result;
+
+Loverflow:
+    onOutOfMemoryError();
+}
+
+/**
+ *
+ */
+extern (C) ulong _d_newarraymT(TypeInfo ti, int ndims, ...)
+{
+    ulong result;
+
+    debug(PRINTF) printf("_d_newarraymT(ndims = %d)\n", ndims);
+    if (ndims == 0)
+        result = 0;
+    else
+    {   va_list q;
+        va_start!(int)(q, ndims);
+
+        void[] foo(TypeInfo ti, size_t* pdim, int ndims)
+        {
+            size_t dim = *pdim;
+            void[] p;
+
+            debug(PRINTF) printf("foo(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, ndims);
+            if (ndims == 1)
+            {
+                auto r = _d_newarrayT(ti, dim);
+                p = *cast(void[]*)(&r);
+            }
+            else
+            {
+                p = gc_malloc(dim * (void[]).sizeof + 1)[0 .. dim];
+                for (int i = 0; i < dim; i++)
+                {
+                    (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1);
+                }
+            }
+            return p;
+        }
+
+        size_t* pdim = cast(size_t *)q;
+        result = cast(ulong)foo(ti, pdim, ndims);
+        debug(PRINTF) printf("result = %llx\n", result);
+
+        version (none)
+        {
+            for (int i = 0; i < ndims; i++)
+            {
+                printf("index %d: %d\n", i, va_arg!(int)(q));
+            }
+        }
+        va_end(q);
+    }
+    return result;
+}
+
+
+/**
+ *
+ */
+extern (C) ulong _d_newarraymiT(TypeInfo ti, int ndims, ...)
+{
+    ulong result;
+
+    debug(PRINTF) printf("_d_newarraymiT(ndims = %d)\n", ndims);
+    if (ndims == 0)
+        result = 0;
+    else
+    {
+        va_list q;
+        va_start!(int)(q, ndims);
+
+        void[] foo(TypeInfo ti, size_t* pdim, int ndims)
+        {
+            size_t dim = *pdim;
+            void[] p;
+
+            if (ndims == 1)
+            {
+                auto r = _d_newarrayiT(ti, dim);
+                p = *cast(void[]*)(&r);
+            }
+            else
+            {
+                p = gc_malloc(dim * (void[]).sizeof + 1)[0 .. dim];
+                for (int i = 0; i < dim; i++)
+                {
+                    (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1);
+                }
+            }
+            return p;
+        }
+
+        size_t* pdim = cast(size_t *)q;
+        result = cast(ulong)foo(ti, pdim, ndims);
+        debug(PRINTF) printf("result = %llx\n", result);
+
+        version (none)
+        {
+            for (int i = 0; i < ndims; i++)
+            {
+                printf("index %d: %d\n", i, va_arg!(int)(q));
+                printf("init = %d\n", va_arg!(int)(q));
+            }
+        }
+        va_end(q);
+    }
+    return result;
+}
+
+
+/**
+ *
+ */
+struct Array
+{
+    size_t length;
+    byte*  data;
+}
+
+
+/**
+ * This function has been replaced by _d_delarray_t
+ */
+extern (C) void _d_delarray(Array *p)
+{
+    if (p)
+    {
+        assert(!p.length || p.data);
+
+        if (p.data)
+            gc_free(p.data);
+        p.data = null;
+        p.length = 0;
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void _d_delarray_t(Array *p, TypeInfo ti)
+{
+    if (p)
+    {
+        assert(!p.length || p.data);
+        if (p.data)
+        {
+            if (ti)
+            {
+                // Call destructors on all the sub-objects
+                auto sz = ti.tsize();
+                auto pe = p.data;
+                auto pend = pe + p.length * sz;
+                while (pe != pend)
+                {
+                    pend -= sz;
+                    ti.destroy(pend);
+                }
+            }
+            gc_free(p.data);
+        }
+        p.data = null;
+        p.length = 0;
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void _d_delmemory(void* *p)
+{
+    if (*p)
+    {
+        gc_free(*p);
+        *p = null;
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void _d_callinterfacefinalizer(void *p)
+{
+    if (p)
+    {
+        Interface *pi = **cast(Interface ***)p;
+        Object o = cast(Object)(p - pi.offset);
+        rt_finalize(cast(void*)o);
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void _d_callfinalizer(void* p)
+{
+    rt_finalize( p );
+}
+
+
+/**
+ *
+ */
+extern (C) void  rt_setCollectHandler(CollectHandler h)
+{
+    collectHandler = h;
+}
+
+
+/**
+ *
+ */
+extern (C) void rt_finalize(void* p, bool det = true)
+{
+    debug(PRINTF) printf("rt_finalize(p = %p)\n", p);
+
+    if (p) // not necessary if called from gc
+    {
+        ClassInfo** pc = cast(ClassInfo**)p;
+
+        if (*pc)
+        {
+            ClassInfo c = **pc;
+
+            try
+            {
+                if (det || collectHandler is null || collectHandler(cast(Object)p))
+                {
+                    do
+                    {
+                        if (c.destructor)
+                        {
+                            fp_t fp = cast(fp_t)c.destructor;
+                            (*fp)(cast(Object)p); // call destructor
+                        }
+                        c = c.base;
+                    } while (c);
+                }
+                if ((cast(void**)p)[1]) // if monitor is not null
+                    _d_monitordelete(cast(Object)p, det);
+            }
+            catch (Throwable e)
+            {
+                onFinalizeError(**pc, e);
+            }
+            finally
+            {
+                *pc = null; // zero vptr
+            }
+        }
+    }
+}
+
+
+/**
+ * Resize dynamic arrays with 0 initializers.
+ */
+extern (C) byte[] _d_arraysetlengthT(TypeInfo ti, size_t newlength, Array *p)
+in
+{
+    assert(ti);
+    assert(!p.length || p.data);
+}
+body
+{
+    debug(PRINTF)
+    {
+        printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength);
+        if (p)
+            printf("\tp.data = %p, p.length = %d\n", p.data, p.length);
+    }
+
+    byte* newdata = void;
+    if (newlength)
+    {
+	if (newlength <= p.length)
+	{
+	    p.length = newlength;
+	    newdata = p.data;
+	    return newdata[0 .. newlength];
+	}
+	size_t sizeelem = ti.next.tsize();
+        version (D_InlineAsm_X86)
+        {
+            size_t newsize = void;
+
+            asm
+            {
+                mov EAX, newlength;
+                mul EAX, sizeelem;
+                mov newsize, EAX;
+                jc  Loverflow;
+            }
+        }
+        else
+        {
+            size_t newsize = sizeelem * newlength;
+
+            if (newsize / newlength != sizeelem)
+                goto Loverflow;
+        }
+
+        debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength);
+
+        if (p.data)
+        {
+            newdata = p.data;
+            if (newlength > p.length)
+            {
+                size_t size = p.length * sizeelem;
+                auto   info = gc_query(p.data);
+
+                if (info.size <= newsize || info.base != p.data)
+                {
+                    if (info.size >= PAGESIZE && info.base == p.data)
+                    {   // Try to extend in-place
+                        auto u = gc_extend(p.data, (newsize + 1) - info.size, (newsize + 1) - info.size);
+                        if (u)
+                        {
+                            goto L1;
+                        }
+                    }
+                    newdata = cast(byte *)gc_malloc(newsize + 1, info.attr);
+                    newdata[0 .. size] = p.data[0 .. size];
+                }
+             L1:
+                newdata[size .. newsize] = 0;
+            }
+        }
+        else
+        {
+            newdata = cast(byte *)gc_calloc(newsize + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        }
+    }
+    else
+    {
+        newdata = p.data;
+    }
+
+    p.data = newdata;
+    p.length = newlength;
+    return newdata[0 .. newlength];
+
+Loverflow:
+    onOutOfMemoryError();
+}
+
+
+/**
+ * Resize arrays for non-zero initializers.
+ *      p               pointer to array lvalue to be updated
+ *      newlength       new .length property of array
+ *      sizeelem        size of each element of array
+ *      initsize        size of initializer
+ *      ...             initializer
+ */
+extern (C) byte[] _d_arraysetlengthiT(TypeInfo ti, size_t newlength, Array *p)
+in
+{
+    assert(!p.length || p.data);
+}
+body
+{
+    byte* newdata;
+    size_t sizeelem = ti.next.tsize();
+    void[] initializer = ti.next.init();
+    size_t initsize = initializer.length;
+
+    assert(sizeelem);
+    assert(initsize);
+    assert(initsize <= sizeelem);
+    assert((sizeelem / initsize) * initsize == sizeelem);
+
+    debug(PRINTF)
+    {
+        printf("_d_arraysetlengthiT(p = %p, sizeelem = %d, newlength = %d, initsize = %d)\n", p, sizeelem, newlength, initsize);
+        if (p)
+            printf("\tp.data = %p, p.length = %d\n", p.data, p.length);
+    }
+
+    if (newlength)
+    {
+        version (D_InlineAsm_X86)
+        {
+            size_t newsize = void;
+
+            asm
+            {
+                mov     EAX,newlength   ;
+                mul     EAX,sizeelem    ;
+                mov     newsize,EAX     ;
+                jc      Loverflow       ;
+            }
+        }
+        else
+        {
+            size_t newsize = sizeelem * newlength;
+
+            if (newsize / newlength != sizeelem)
+                goto Loverflow;
+        }
+        debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength);
+
+        size_t size = p.length * sizeelem;
+
+        if (p.data)
+        {
+            newdata = p.data;
+            if (newlength > p.length)
+            {
+                auto info = gc_query(p.data);
+
+                if (info.size <= newsize || info.base != p.data)
+                {
+                    if (info.size >= PAGESIZE && info.base == p.data)
+                    {   // Try to extend in-place
+                        auto u = gc_extend(p.data, (newsize + 1) - info.size, (newsize + 1) - info.size);
+                        if (u)
+                        {
+                            goto L1;
+                        }
+                    }
+                    newdata = cast(byte *)gc_malloc(newsize + 1, info.attr);
+                    newdata[0 .. size] = p.data[0 .. size];
+                L1: ;
+                }
+            }
+        }
+        else
+        {
+            newdata = cast(byte *)gc_malloc(newsize + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        }
+
+        auto q = initializer.ptr; // pointer to initializer
+
+        if (newsize > size)
+        {
+            if (initsize == 1)
+            {
+                debug(PRINTF) printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q);
+                newdata[size .. newsize] = *(cast(byte*)q);
+            }
+            else
+            {
+                for (size_t u = size; u < newsize; u += initsize)
+                {
+                    memcpy(newdata + u, q, initsize);
+                }
+            }
+        }
+    }
+    else
+    {
+        newdata = p.data;
+    }
+
+    p.data = newdata;
+    p.length = newlength;
+    return newdata[0 .. newlength];
+
+Loverflow:
+    onOutOfMemoryError();
+}
+
+
+/**
+ * Append y[] to array x[].
+ * size is size of each array element.
+ */
+extern (C) long _d_arrayappendT(TypeInfo ti, Array *px, byte[] y)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    auto info = gc_query(px.data);
+    auto length = px.length;
+    auto newlength = length + y.length;
+    auto newsize = newlength * sizeelem;
+
+    if (info.size < newsize || info.base != px.data)
+    {   byte* newdata;
+
+        if (info.size >= PAGESIZE && info.base == px.data)
+        {   // Try to extend in-place
+            auto u = gc_extend(px.data, (newsize + 1) - info.size, (newsize + 1) - info.size);
+            if (u)
+            {
+                goto L1;
+            }
+        }
+        newdata = cast(byte *)gc_malloc(newCapacity(newlength, sizeelem) + 1, info.attr);
+        memcpy(newdata, px.data, length * sizeelem);
+        px.data = newdata;
+    }
+  L1:
+    px.length = newlength;
+    memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem);
+    return *cast(long*)px;
+}
+
+
+/**
+ *
+ */
+size_t newCapacity(size_t newlength, size_t size)
+{
+    version(none)
+    {
+        size_t newcap = newlength * size;
+    }
+    else
+    {
+        /*
+         * Better version by Dave Fladebo:
+         * This uses an inverse logorithmic algorithm to pre-allocate a bit more
+         * space for larger arrays.
+         * - Arrays smaller than PAGESIZE bytes are left as-is, so for the most
+         * common cases, memory allocation is 1 to 1. The small overhead added
+         * doesn't affect small array perf. (it's virtually the same as
+         * current).
+         * - Larger arrays have some space pre-allocated.
+         * - As the arrays grow, the relative pre-allocated space shrinks.
+         * - The logorithmic algorithm allocates relatively more space for
+         * mid-size arrays, making it very fast for medium arrays (for
+         * mid-to-large arrays, this turns out to be quite a bit faster than the
+         * equivalent realloc() code in C, on Linux at least. Small arrays are
+         * just as fast as GCC).
+         * - Perhaps most importantly, overall memory usage and stress on the GC
+         * is decreased significantly for demanding environments.
+         */
+        size_t newcap = newlength * size;
+        size_t newext = 0;
+
+        if (newcap > PAGESIZE)
+        {
+            //double mult2 = 1.0 + (size / log10(pow(newcap * 2.0,2.0)));
+
+            // redo above line using only integer math
+
+            static int log2plus1(size_t c)
+            {   int i;
+
+                if (c == 0)
+                    i = -1;
+                else
+                    for (i = 1; c >>= 1; i++)
+                    {
+                    }
+                return i;
+            }
+
+            /* The following setting for mult sets how much bigger
+             * the new size will be over what is actually needed.
+             * 100 means the same size, more means proportionally more.
+             * More means faster but more memory consumption.
+             */
+            //long mult = 100 + (1000L * size) / (6 * log2plus1(newcap));
+            long mult = 100 + (1000L * size) / log2plus1(newcap);
+
+            // testing shows 1.02 for large arrays is about the point of diminishing return
+            if (mult < 102)
+                mult = 102;
+            newext = cast(size_t)((newcap * mult) / 100);
+            newext -= newext % size;
+            debug(PRINTF) printf("mult: %2.2f, alloc: %2.2f\n",mult/100.0,newext / cast(double)size);
+        }
+        newcap = newext > newcap ? newext : newcap;
+        debug(PRINTF) printf("newcap = %d, newlength = %d, size = %d\n", newcap, newlength, size);
+    }
+    return newcap;
+}
+
+
+/**
+ *
+ */
+extern (C) byte[] _d_arrayappendcT(TypeInfo ti, inout byte[] x, ...)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    auto info = gc_query(x.ptr);
+    auto length = x.length;
+    auto newlength = length + 1;
+    auto newsize = newlength * sizeelem;
+
+    assert(info.size == 0 || length * sizeelem <= info.size);
+
+    debug(PRINTF) printf("_d_arrayappendcT(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, info.size);
+
+    if (info.size <= newsize || info.base != x.ptr)
+    {   byte* newdata;
+
+        if (info.size >= PAGESIZE && info.base == x.ptr)
+        {   // Try to extend in-place
+            auto u = gc_extend(x.ptr, (newsize + 1) - info.size, (newsize + 1) - info.size);
+            if (u)
+            {
+                goto L1;
+            }
+        }
+        debug(PRINTF) printf("_d_arrayappendcT(length = %d, newlength = %d, cap = %d)\n", length, newlength, info.size);
+        auto newcap = newCapacity(newlength, sizeelem);
+        assert(newcap >= newlength * sizeelem);
+        newdata = cast(byte *)gc_malloc(newcap + 1, info.attr);
+        memcpy(newdata, x.ptr, length * sizeelem);
+        (cast(void**)(&x))[1] = newdata;
+    }
+  L1:
+    byte *argp = cast(byte *)(&ti + 2);
+
+    *cast(size_t *)&x = newlength;
+    x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem];
+    assert((cast(size_t)x.ptr & 15) == 0);
+    assert(gc_sizeOf(x.ptr) > x.length * sizeelem);
+    return x;
+}
+
+
+/**
+ *
+ */
+extern (C) byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y)
+out (result)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, sizeelem, result.length, result.ptr);
+    assert(result.length == x.length + y.length);
+    for (size_t i = 0; i < x.length * sizeelem; i++)
+        assert((cast(byte*)result)[i] == (cast(byte*)x)[i]);
+    for (size_t i = 0; i < y.length * sizeelem; i++)
+        assert((cast(byte*)result)[x.length * sizeelem + i] == (cast(byte*)y)[i]);
+
+    size_t cap = gc_sizeOf(result.ptr);
+    assert(!cap || cap > result.length * sizeelem);
+}
+body
+{
+    version (none)
+    {
+        /* Cannot use this optimization because:
+         *  char[] a, b;
+         *  char c = 'a';
+         *  b = a ~ c;
+         *  c = 'b';
+         * will change the contents of b.
+         */
+        if (!y.length)
+            return x;
+        if (!x.length)
+            return y;
+    }
+
+    debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p)\n", x.length, x.ptr, y.length, y.ptr);
+    auto sizeelem = ti.next.tsize();            // array element size
+    debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d)\n", x.length, x.ptr, y.length, y.ptr, sizeelem);
+    size_t xlen = x.length * sizeelem;
+    size_t ylen = y.length * sizeelem;
+    size_t len  = xlen + ylen;
+
+    if (!len)
+        return null;
+
+    byte* p = cast(byte*)gc_malloc(len + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+    memcpy(p, x.ptr, xlen);
+    memcpy(p + xlen, y.ptr, ylen);
+    p[len] = 0;
+    return p[0 .. x.length + y.length];
+}
+
+
+/**
+ *
+ */
+extern (C) byte[] _d_arraycatnT(TypeInfo ti, uint n, ...)
+{   void* a;
+    size_t length;
+    byte[]* p;
+    uint i;
+    byte[] b;
+    auto size = ti.next.tsize(); // array element size
+
+    p = cast(byte[]*)(&n + 1);
+
+    for (i = 0; i < n; i++)
+    {
+        b = *p++;
+        length += b.length;
+    }
+    if (!length)
+        return null;
+
+    a = gc_malloc(length * size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+    p = cast(byte[]*)(&n + 1);
+
+    uint j = 0;
+    for (i = 0; i < n; i++)
+    {
+        b = *p++;
+        if (b.length)
+        {
+            memcpy(a + j, b.ptr, b.length * size);
+            j += b.length * size;
+        }
+    }
+
+    byte[] result;
+    *cast(int *)&result = length;       // jam length
+    (cast(void **)&result)[1] = a;      // jam ptr
+    return result;
+}
+
+
+/**
+ *
+ */
+extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    void* result;
+
+    debug(PRINTF) printf("_d_arrayliteralT(sizeelem = %d, length = %d)\n", sizeelem, length);
+    if (length == 0 || sizeelem == 0)
+        result = null;
+    else
+    {
+        result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+
+        va_list q;
+        va_start!(size_t)(q, length);
+
+        size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1);
+
+        if (stacksize == sizeelem)
+        {
+            memcpy(result, q, length * sizeelem);
+        }
+        else
+        {
+            for (size_t i = 0; i < length; i++)
+            {
+                memcpy(result + i * sizeelem, q, sizeelem);
+                q += stacksize;
+            }
+        }
+
+        va_end(q);
+    }
+    return result;
+}
+
+
+/**
+ * Support for array.dup property.
+ */
+struct Array2
+{
+    size_t length;
+    void*  ptr;
+}
+
+
+/**
+ *
+ */
+extern (C) long _adDupT(TypeInfo ti, Array2 a)
+out (result)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    assert(memcmp((*cast(Array2*)&result).ptr, a.ptr, a.length * sizeelem) == 0);
+}
+body
+{
+    Array2 r;
+
+    if (a.length)
+    {
+        auto sizeelem = ti.next.tsize();                // array element size
+        auto size = a.length * sizeelem;
+        r.ptr = gc_malloc(size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        r.length = a.length;
+        memcpy(r.ptr, a.ptr, size);
+    }
+    return *cast(long*)(&r);
+}
+
+
+unittest
+{
+    int[] a;
+    int[] b;
+    int i;
+
+    a = new int[3];
+    a[0] = 1; a[1] = 2; a[2] = 3;
+    b = a.dup;
+    assert(b.length == 3);
+    for (i = 0; i < 3; i++)
+        assert(b[i] == i + 1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/llmath.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,531 @@
+/**
+ * Support for 64-bit longs.
+ *
+ * Copyright: Copyright Digital Mars 1993 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 1993 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.llmath;
+
+extern (C):
+
+
+/***************************************
+ * Unsigned long divide.
+ * Input:
+ *      [EDX,EAX],[ECX,EBX]
+ * Output:
+ *      [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
+ *      [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
+ */
+
+void __ULDIV__()
+{
+    asm
+    {
+        naked                   ;
+        test    ECX,ECX         ;
+        jz      uldiv           ;
+
+        // if ECX > EDX, then quotient is 0 and remainder is [EDX,EAX]
+        cmp     ECX,EDX         ;
+        ja      quo0            ;
+
+        test    ECX,ECX         ;
+        js      Lleft           ;
+
+        /* We have n>d, and know that n/d will fit in 32 bits.
+         * d will be left justified if we shift it left s bits.
+         * [d1,d0] <<= s
+         * [n2,n1,n0] = [n1,n0] << s
+         *
+         * Use one divide, by this reasoning:
+         * ([n2,n1]<<32 + n0)/(d1<<32 + d0)
+         * becomes:
+         * ([n2,n1]<<32)/(d1<<32 + d0) + n0/(d1<<32 + d0)
+         * The second divide is always 0.
+         * Ignore the d0 in the first divide, which will yield a quotient
+         * that might be too high by 1 (because d1 is left justified).
+         * We can tell if it's too big if:
+         *  q*[d1,d0] > [n2,n1,n0]
+         * which is:
+         *  q*[d1,d0] > [[q*[d1,0]+q%[d1,0],n1,n0]
+         * If we subtract q*[d1,0] from both sides, we get:
+         *  q*d0 > [[n2,n1]%d1,n0]
+         * So if it is too big by one, reduce q by one to q'=q-one.
+         * Compute remainder as:
+         *  r = ([n1,n0] - q'*[d1,d0]) >> s
+         * Again, we can subtract q*[d1,0]:
+         *  r = ([n1,n0] - q*[d1,0] - (q'*[d1,d0] - q*[d1,0])) >> s
+         *  r = ([[n2,n1]%d1,n0] + (q*[d1,0] - (q - one)*[d1,d0])) >> s
+         *  r = ([[n2,n1]%d1,n0] + (q*[d1,0] - [d1 *(q-one),d0*(1-q)])) >> s
+         *  r = ([[n2,n1]%d1,n0] + [d1 *one,d0*(one-q)])) >> s
+         */
+
+        push    EBP             ;
+        push    ESI             ;
+        push    EDI             ;
+
+        mov     ESI,EDX         ;
+        mov     EDI,EAX         ;
+        mov     EBP,ECX         ;
+
+        bsr     EAX,ECX         ;       // EAX is now 30..0
+        xor     EAX,0x1F        ;       // EAX is now 1..31
+        mov     CH,AL           ;
+        neg     EAX             ;
+        add     EAX,32          ;
+        mov     CL,AL           ;
+
+        mov     EAX,EBX         ;
+        shr     EAX,CL          ;
+        xchg    CH,CL           ;
+        shl     EBP,CL          ;
+        or      EBP,EAX         ;
+        shl     EBX,CL          ;
+
+        mov     EDX,ESI         ;
+        xchg    CH,CL           ;
+        shr     EDX,CL          ;
+
+        mov     EAX,EDI         ;
+        shr     EAX,CL          ;
+        xchg    CH,CL           ;
+        shl     EDI,CL          ;
+        shl     ESI,CL          ;
+        or      EAX,ESI         ;
+
+        div     EBP             ;
+        push    EBP             ;
+        mov     EBP,EAX         ;
+        mov     ESI,EDX         ;
+
+        mul     EBX             ;
+        cmp     EDX,ESI         ;
+        ja      L1              ;
+        jb      L2              ;
+        cmp     EAX,EDI         ;
+        jbe     L2              ;
+L1:     dec     EBP             ;
+        sub     EAX,EBX         ;
+        sbb     EDX,0[ESP]      ;
+L2:
+        add     ESP,4           ;
+        sub     EDI,EAX         ;
+        sbb     ESI,EDX         ;
+        mov     EAX,ESI         ;
+        xchg    CH,CL           ;
+        shl     EAX,CL          ;
+        xchg    CH,CL           ;
+        shr     EDI,CL          ;
+        or      EDI,EAX         ;
+        shr     ESI,CL          ;
+        mov     EBX,EDI         ;
+        mov     ECX,ESI         ;
+        mov     EAX,EBP         ;
+        xor     EDX,EDX         ;
+
+        pop     EDI             ;
+        pop     ESI             ;
+        pop     EBP             ;
+        ret                     ;
+
+uldiv:  test    EDX,EDX         ;
+        jnz     D3              ;
+        // Both high words are 0, we can use the DIV instruction
+        div     EBX             ;
+        mov     EBX,EDX         ;
+        mov     EDX,ECX         ;       // EDX = ECX = 0
+        ret                     ;
+
+        even                    ;
+D3:     // Divide [EDX,EAX] by EBX
+        mov     ECX,EAX         ;
+        mov     EAX,EDX         ;
+        xor     EDX,EDX         ;
+        div     EBX             ;
+        xchg    ECX,EAX         ;
+        div     EBX             ;
+        // ECX,EAX = result
+        // EDX = remainder
+        mov     EBX,EDX         ;
+        mov     EDX,ECX         ;
+        xor     ECX,ECX         ;
+        ret                     ;
+
+quo0:   // Quotient is 0
+        // Remainder is [EDX,EAX]
+        mov     EBX,EAX         ;
+        mov     ECX,EDX         ;
+        xor     EAX,EAX         ;
+        xor     EDX,EDX         ;
+        ret                     ;
+
+Lleft:  // The quotient is 0 or 1 and EDX >= ECX
+        cmp     EDX,ECX         ;
+        ja      quo1            ;       // [EDX,EAX] > [ECX,EBX]
+        // EDX == ECX
+        cmp     EAX,EBX         ;
+        jb      quo0            ;
+
+quo1:   // Quotient is 1
+        // Remainder is [EDX,EAX] - [ECX,EBX]
+        sub     EAX,EBX         ;
+        sbb     EDX,ECX         ;
+        mov     EBX,EAX         ;
+        mov     ECX,EDX         ;
+        mov     EAX,1           ;
+        xor     EDX,EDX         ;
+        ret                     ;
+    }
+}
+
+
+/***************************************
+ * Signed long divide.
+ * Input:
+ *      [EDX,EAX],[ECX,EBX]
+ * Output:
+ *      [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
+ *      [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
+ *      ESI,EDI destroyed
+ */
+
+void __LDIV__()
+{
+    asm
+    {
+        naked                   ;
+        test    EDX,EDX         ;       // [EDX,EAX] negative?
+        jns     L10             ;       // no
+        //neg64 EDX,EAX         ;       // [EDX,EAX] = -[EDX,EAX]
+          neg   EDX             ;
+          neg   EAX             ;
+          sbb   EDX,0           ;
+        test    ECX,ECX         ;       // [ECX,EBX] negative?
+        jns     L11             ;       // no
+        //neg64 ECX,EBX         ;
+          neg   ECX             ;
+          neg   EBX             ;
+          sbb   ECX,0           ;
+        call    __ULDIV__       ;
+        //neg64 ECX,EBX         ;       // remainder same sign as dividend
+          neg   ECX             ;
+          neg   EBX             ;
+          sbb   ECX,0           ;
+        ret                     ;
+
+L11:    call    __ULDIV__       ;
+        //neg64 ECX,EBX         ;       // remainder same sign as dividend
+          neg   ECX             ;
+          neg   EBX             ;
+          sbb   ECX,0           ;
+        //neg64 EDX,EAX         ;       // quotient is negative
+          neg   EDX             ;
+          neg   EAX             ;
+          sbb   EDX,0           ;
+        ret                     ;
+
+L10:    test    ECX,ECX         ;       // [ECX,EBX] negative?
+        jns     L12             ;       // no (all is positive)
+        //neg64 ECX,EBX         ;
+          neg   ECX             ;
+          neg   EBX             ;
+          sbb   ECX,0           ;
+        call    __ULDIV__       ;
+        //neg64 EDX,EAX         ;       // quotient is negative
+          neg   EDX             ;
+          neg   EAX             ;
+          sbb   EDX,0           ;
+        ret                     ;
+
+L12:    jmp     __ULDIV__       ;
+    }
+}
+
+
+/***************************************
+ * Compare [EDX,EAX] with [ECX,EBX]
+ * Signed
+ * Returns result in flags
+ */
+
+void __LCMP__()
+{
+    asm
+    {
+        naked                   ;
+        cmp     EDX,ECX         ;
+        jne     C1              ;
+        push    EDX             ;
+        xor     EDX,EDX         ;
+        cmp     EAX,EBX         ;
+        jz      C2              ;
+        ja      C3              ;
+        dec     EDX             ;
+        pop     EDX             ;
+        ret                     ;
+
+C3:     inc     EDX             ;
+C2:     pop     EDX             ;
+C1:     ret                     ;
+    }
+}
+
+
+
+
+// Convert ulong to real
+
+private __gshared real adjust = cast(real)0x800_0000_0000_0000 * 0x10;
+
+real __U64_LDBL()
+{
+    version (OSX)
+    {   /* OSX version has to be concerned about 16 byte stack
+         * alignment and the inability to reference the data segment
+         * because of PIC.
+         */
+        asm
+        {   naked                               ;
+            push        EDX                     ;
+            push        EAX                     ;
+            and         dword ptr 4[ESP], 0x7FFFFFFF    ;
+            fild        qword ptr [ESP]         ;
+            test        EDX,EDX                 ;
+            jns         L1                      ;
+            push        0x0000403e              ;
+            push        0x80000000              ;
+            push        0                       ;
+            fld         real ptr [ESP]          ; // adjust
+            add         ESP,12                  ;
+            faddp       ST(1), ST               ;
+        L1:                                     ;
+            add         ESP, 8                  ;
+            ret                                 ;
+        }
+    }
+    else
+    {
+        asm
+        {   naked                               ;
+            push        EDX                     ;
+            push        EAX                     ;
+            and         dword ptr 4[ESP], 0x7FFFFFFF    ;
+            fild        qword ptr [ESP]         ;
+            test        EDX,EDX                 ;
+            jns         L1                      ;
+            fld         real ptr adjust         ;
+            faddp       ST(1), ST               ;
+        L1:                                     ;
+            add         ESP, 8                  ;
+            ret                                 ;
+        }
+    }
+}
+
+// Same as __U64_LDBL, but return result as double in [EDX,EAX]
+ulong __ULLNGDBL()
+{
+    asm
+    {   naked                                   ;
+        call __U64_LDBL                         ;
+        sub  ESP,8                              ;
+        fstp double ptr [ESP]                   ;
+        pop  EAX                                ;
+        pop  EDX                                ;
+        ret                                     ;
+    }
+}
+
+// Convert double to ulong
+
+private __gshared short roundTo0 = 0xFBF;
+
+ulong __DBLULLNG()
+{
+    // BUG: should handle NAN's and overflows
+    version (OSX)
+    {
+        asm
+        {   naked                               ;
+            push        0xFBF                   ; // roundTo0
+            push        0x0000403e              ;
+            push        0x80000000              ;
+            push        0                       ; // adjust
+            push        EDX                     ;
+            push        EAX                     ;
+            fld         double ptr [ESP]        ;
+            sub         ESP,8                   ;
+            fld         real ptr 16[ESP]        ; // adjust
+            fcomp                               ;
+            fstsw       AX                      ;
+            fstcw       8[ESP]                  ;
+            fldcw       28[ESP]                 ; // roundTo0
+            sahf                                ;
+            jae         L1                      ;
+            fld         real ptr 16[ESP]        ; // adjust
+            fsubp       ST(1), ST               ;
+            fistp       qword ptr [ESP]         ;
+            pop         EAX                     ;
+            pop         EDX                     ;
+            fldcw       [ESP]                   ;
+            add         ESP,24                  ;
+            add         EDX,0x8000_0000         ;
+            ret                                 ;
+        L1:                                     ;
+            fistp       qword ptr [ESP]         ;
+            pop         EAX                     ;
+            pop         EDX                     ;
+            fldcw       [ESP]                   ;
+            add         ESP,24                  ;
+            ret                                 ;
+        }
+    }
+    else
+    {
+        asm
+        {   naked                               ;
+            push        EDX                     ;
+            push        EAX                     ;
+            fld         double ptr [ESP]        ;
+            sub         ESP,8                   ;
+            fld         real ptr adjust         ;
+            fcomp                               ;
+            fstsw       AX                      ;
+            fstcw       8[ESP]                  ;
+            fldcw       roundTo0                ;
+            sahf                                ;
+            jae         L1                      ;
+            fld         real ptr adjust         ;
+            fsubp       ST(1), ST               ;
+            fistp       qword ptr [ESP]         ;
+            pop         EAX                     ;
+            pop         EDX                     ;
+            fldcw       [ESP]                   ;
+            add         ESP,8                   ;
+            add         EDX,0x8000_0000         ;
+            ret                                 ;
+        L1:                                     ;
+            fistp       qword ptr [ESP]         ;
+            pop         EAX                     ;
+            pop         EDX                     ;
+            fldcw       [ESP]                   ;
+            add         ESP,8                   ;
+            ret                                 ;
+        }
+    }
+}
+
+// Convert double in ST0 to uint
+
+uint __DBLULNG()
+{
+    // BUG: should handle NAN's and overflows
+    version (OSX)
+    {
+        asm
+        {   naked                               ;
+            push        0xFBF                   ; // roundTo0
+            sub         ESP,12                  ;
+            fstcw       8[ESP]                  ;
+            fldcw       12[ESP]                 ; // roundTo0
+            fistp       qword ptr [ESP]         ;
+            fldcw       8[ESP]                  ;
+            pop         EAX                     ;
+            add         ESP,12                  ;
+            ret                                 ;
+        }
+    }
+    else
+    {
+        asm
+        {   naked                               ;
+            sub         ESP,16                  ;
+            fstcw       8[ESP]                  ;
+            fldcw       roundTo0                ;
+            fistp       qword ptr [ESP]         ;
+            fldcw       8[ESP]                  ;
+            pop         EAX                     ;
+            add         ESP,12                  ;
+            ret                                 ;
+        }
+    }
+}
+
+// Convert real in ST0 to ulong
+
+ulong __LDBLULLNG()
+{
+    version (OSX)
+    {
+	asm
+	{   naked				;
+	    push	0xFBF			; // roundTo0
+	    push	0x0000403e		;
+	    push	0x80000000		;
+	    push	0			; // adjust
+	    sub		ESP,16			;
+	    fld		real ptr 16[ESP]	; // adjust
+	    fcomp				;
+	    fstsw	AX			;
+	    fstcw	8[ESP]			;
+	    fldcw	28[ESP]			; // roundTo0
+	    sahf				;
+	    jae		L1			;
+	    fld		real ptr 16[ESP]	; // adjust
+	    fsubp	ST(1), ST		;
+	    fistp	qword ptr [ESP]		;
+	    pop		EAX			;
+	    pop		EDX			;
+	    fldcw	[ESP]			;
+	    add		ESP,24			;
+	    add		EDX,0x8000_0000		;
+	    ret					;
+	L1:					;
+	    fistp	qword ptr [ESP]		;
+	    pop		EAX			;
+	    pop		EDX			;
+	    fldcw	[ESP]			;
+	    add		ESP,24			;
+	    ret					;
+	}
+    }
+    else
+    {
+	asm
+	{   naked				;
+	    sub		ESP,16			;
+	    fld		real ptr adjust		;
+	    fcomp				;
+	    fstsw	AX			;
+	    fstcw	8[ESP]			;
+	    fldcw	roundTo0		;
+	    sahf				;
+	    jae		L1			;
+	    fld		real ptr adjust		;
+	    fsubp	ST(1), ST		;
+	    fistp	qword ptr [ESP]		;
+	    pop		EAX			;
+	    pop		EDX			;
+	    fldcw	[ESP]			;
+	    add		ESP,8			;
+	    add		EDX,0x8000_0000		;
+	    ret					;
+	L1:					;
+	    fistp	qword ptr [ESP]		;
+	    pop		EAX			;
+	    pop		EDX			;
+	    fldcw	[ESP]			;
+	    add		ESP,8			;
+	    ret					;
+	}
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/mars.h	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,105 @@
+/**
+ * Common declarations for runtime implementation.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#include <stddef.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+struct ClassInfo;
+struct Vtbl;
+
+typedef struct Vtbl
+{
+    size_t len;
+    void **vptr;
+} Vtbl;
+
+typedef struct Interface
+{
+    struct ClassInfo *classinfo;
+    struct Vtbl vtbl;
+    int offset;
+} Interface;
+
+typedef struct Object
+{
+    void **vptr;
+    void *monitor;
+} Object;
+
+typedef struct ClassInfo
+{
+    Object object;
+
+    size_t initlen;
+    void *init;
+
+    size_t namelen;
+    char *name;
+
+    Vtbl vtbl;
+
+    size_t interfacelen;
+    Interface *interfaces;
+
+    struct ClassInfo *baseClass;
+
+    void *destructor;
+    void *invariant;
+
+    int flags;
+} ClassInfo;
+
+typedef struct Throwable
+{
+    Object object;
+
+    size_t msglen;
+    char*  msg;
+
+    size_t filelen;
+    char*  file;
+
+    size_t line;
+
+    struct Interface *info;
+    struct Throwable *next;
+} Throwable;
+
+typedef struct Array
+{
+    size_t length;
+    void *ptr;
+} Array;
+
+typedef struct Delegate
+{
+    void *thisptr;
+    void (*funcptr)();
+} Delegate;
+
+void _d_monitorenter(Object *h);
+void _d_monitorexit(Object *h);
+
+int _d_isbaseof(ClassInfo *b, ClassInfo *c);
+Object *_d_dynamic_cast(Object *o, ClassInfo *ci);
+
+Object * _d_newclass(ClassInfo *ci);
+void _d_delclass(Object **p);
+
+void _d_OutOfMemory();
+
+#if __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/memory.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,213 @@
+/**
+ * This module exposes functionality for inspecting and manipulating memory.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.memory;
+
+
+private
+{
+    version( linux )
+    {
+        version = SimpleLibcStackEnd;
+
+        version( SimpleLibcStackEnd )
+        {
+            extern (C) extern __gshared void* __libc_stack_end;
+        }
+    }
+    version( FreeBSD )
+    {
+        version = SimpleLibcStackEnd;
+
+        version( SimpleLibcStackEnd )
+        {
+            extern (C) extern __gshared void* __libc_stack_end;
+        }
+    }
+    version( Solaris )
+    {
+        version = SimpleLibcStackEnd;
+
+        version( SimpleLibcStackEnd )
+        {
+            extern (C) extern __gshared void* __libc_stack_end;
+        }
+    }
+    extern (C) void gc_addRange( void* p, size_t sz );
+    extern (C) void gc_removeRange( void* p );
+}
+
+
+/**
+ *
+ */
+extern (C) void* rt_stackBottom()
+{
+    version( Windows )
+    {
+        asm
+        {
+            naked;
+            mov EAX,FS:4;
+            ret;
+        }
+    }
+    else version( linux )
+    {
+        version( SimpleLibcStackEnd )
+        {
+            return __libc_stack_end;
+        }
+        else
+        {
+            // See discussion: http://autopackage.org/forums/viewtopic.php?t=22
+            static void** libc_stack_end;
+
+            if( libc_stack_end == libc_stack_end.init )
+            {
+                void* handle = dlopen( null, RTLD_NOW );
+                libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" );
+                dlclose( handle );
+            }
+            return *libc_stack_end;
+        }
+    }
+    else version( OSX )
+    {
+        return cast(void*) 0xc0000000;
+    }
+    else version( FreeBSD )
+    {
+	return __libc_stack_end;
+    }
+    else version( Solaris )
+    {
+	return __libc_stack_end;
+    }
+    else
+    {
+        static assert( false, "Operating system not supported." );
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void* rt_stackTop()
+{
+    version( D_InlineAsm_X86 )
+    {
+        asm
+        {
+            naked;
+            mov EAX, ESP;
+            ret;
+        }
+    }
+    else
+    {
+        static assert( false, "Architecture not supported." );
+    }
+}
+
+
+private
+{
+    version( Windows )
+    {
+        extern (C)
+        {
+	    extern __gshared
+	    {
+		int _xi_a;   // &_xi_a just happens to be start of data segment
+		int _edata;  // &_edata is start of BSS segment
+		int _end;    // &_end is past end of BSS
+	    }
+        }
+    }
+    else version( linux )
+    {
+        extern (C)
+        {
+	    extern __gshared
+	    {
+		int _data;
+		int __data_start;
+		int _end;
+		int _data_start__;
+		int _data_end__;
+		int _bss_start__;
+		int _bss_end__;
+		int __fini_array_end;
+	    }
+        }
+
+            alias __data_start  Data_Start;
+            alias _end          Data_End;
+    }
+    else version( OSX )
+    {
+        extern (C) void _d_osx_image_init();
+    }
+    else version( FreeBSD )
+    {
+        extern (C)
+        {
+	    extern __gshared
+	    {
+		int etext;
+		int _end;
+	    }
+        }
+    }
+    else version( Solaris )
+    {
+        extern (C)
+        {
+	    extern __gshared
+	    {
+		int etext;
+		int _end;
+	    }
+        }
+    }
+}
+
+
+void initStaticDataGC()
+{
+    version( Windows )
+    {
+        gc_addRange( &_xi_a, cast(size_t) &_end - cast(size_t) &_xi_a );
+    }
+    else version( linux )
+    {
+        gc_addRange( &__data_start, cast(size_t) &_end - cast(size_t) &__data_start );
+    }
+    else version( OSX )
+    {
+        _d_osx_image_init();
+    }
+    else version( FreeBSD )
+    {
+        gc_addRange( &etext, cast(size_t) &_end - cast(size_t) &etext );
+    }
+    else version( Solaris )
+    {
+        gc_addRange( &etext, cast(size_t) &_end - cast(size_t) &etext );
+    }
+    else
+    {
+        static assert( false, "Operating system not supported." );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/memory_osx.c	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,75 @@
+/**
+ * This module provides OSX-specific support routines for memory.d.
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifdef __APPLE__
+
+
+#include <mach-o/dyld.h>
+#include <mach-o/getsect.h>
+
+void gc_addRange( void* p, size_t sz );
+void gc_removeRange( void* p );
+
+typedef struct
+{
+    const char* seg;
+    const char* sect;
+} seg_ref;
+
+const static seg_ref data_segs[] = {{SEG_DATA, SECT_DATA},
+                                    {SEG_DATA, SECT_BSS},
+                                    {SEG_DATA, SECT_COMMON}};
+const static int NUM_DATA_SEGS   = sizeof(data_segs) / sizeof(seg_ref);
+
+
+static void on_add_image( const struct mach_header* h, intptr_t slide )
+{
+    const struct section* sect;
+    int i;
+
+    for( i = 0; i < NUM_DATA_SEGS; ++i )
+    {
+        sect = getsectbynamefromheader( h,
+                                        data_segs[i].seg,
+                                        data_segs[i].sect );
+        if( sect == NULL || sect->size == 0 )
+            continue;
+        gc_addRange( (void*) sect->addr + slide, sect->size );
+    }
+}
+
+
+static void on_remove_image( const struct mach_header* h, intptr_t slide )
+{
+    const struct section* sect;
+    int i;
+
+    for( i = 0; i < NUM_DATA_SEGS; ++i )
+    {
+        sect = getsectbynamefromheader( h,
+                                        data_segs[i].seg,
+                                        data_segs[i].sect );
+        if( sect == NULL || sect->size == 0 )
+            continue;
+        gc_removeRange( (void*) sect->addr + slide );
+    }
+}
+
+
+void _d_osx_image_init()
+{
+    _dyld_register_func_for_add_image( &on_add_image );
+    _dyld_register_func_for_remove_image( &on_remove_image );
+}
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/memset.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,109 @@
+/**
+ * Contains a memset implementation used by compiler-generated code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.memset;
+
+extern (C)
+{
+    // Functions from the C library.
+    void *memcpy(void *, void *, size_t);
+}
+
+extern (C):
+
+short *_memset16(short *p, short value, size_t count)
+{
+    short *pstart = p;
+    short *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+
+int *_memset32(int *p, int value, size_t count)
+{
+version (X86)
+{
+    asm
+    {
+        mov     EDI,p           ;
+        mov     EAX,value       ;
+        mov     ECX,count       ;
+        mov     EDX,EDI         ;
+        rep                     ;
+        stosd                   ;
+        mov     EAX,EDX         ;
+    }
+}
+else
+{
+    int *pstart = p;
+    int *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+}
+
+long *_memset64(long *p, long value, size_t count)
+{
+    long *pstart = p;
+    long *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+
+cdouble *_memset128(cdouble *p, cdouble value, size_t count)
+{
+    cdouble *pstart = p;
+    cdouble *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+
+real *_memset80(real *p, real value, size_t count)
+{
+    real *pstart = p;
+    real *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+
+creal *_memset160(creal *p, creal value, size_t count)
+{
+    creal *pstart = p;
+    creal *ptop;
+
+    for (ptop = &p[count]; p < ptop; p++)
+        *p = value;
+    return pstart;
+}
+
+void *_memsetn(void *p, void *value, int count, size_t sizelem)
+{   void *pstart = p;
+    int i;
+
+    for (i = 0; i < count; i++)
+    {
+        memcpy(p, value, sizelem);
+        p = cast(void *)(cast(char *)p + sizelem);
+    }
+    return pstart;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/minit.asm	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,85 @@
+;_ minit.asm
+;  Module initialization support.
+; 
+;  Copyright: Copyright Digital Mars 2000 - 2009.
+;  License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+;  Authors:   Walter Bright
+; 
+;           Copyright Digital Mars 2000 - 2009.
+;  Distributed under the Boost Software License, Version 1.0.
+;     (See accompanying file LICENSE_1_0.txt or copy at
+;           http://www.boost.org/LICENSE_1_0.txt)
+;
+include macros.asm
+
+ifdef _WIN32
+  DATAGRP      EQU     FLAT
+else
+  DATAGRP      EQU     DGROUP
+endif
+
+; Provide a default resolution for weak extern records, no way in C
+; to define an omf symbol with a specific value
+public __nullext
+__nullext   equ 0
+
+    extrn   __moduleinfo_array:near
+
+; This bit of assembler is needed because, from C or D, one cannot
+; specify the names of data segments. Why does this matter?
+; All the ModuleInfo pointers are placed into a segment named 'FM'.
+; The order in which they are placed in 'FM' is arbitrarily up to the linker.
+; In order to walk all the pointers, we need to be able to find the
+; beginning and the end of the 'FM' segment.
+; This is done by bracketing the 'FM' segment with two other, empty,
+; segments named 'FMB' and 'FME'. Since this module is the only one that
+; ever refers to 'FMB' and 'FME', we get to control the order in which
+; these segments appear relative to 'FM' by using a GROUP statement.
+; So, we have in memory:
+;   FMB empty segment
+;   FM  contains all the pointers
+;   FME empty segment
+; and finding the limits of FM is as easy as taking the address of FMB
+; and the address of FME.
+
+; These segments bracket FM, which contains the list of ModuleInfo pointers
+FMB     segment dword use32 public 'DATA'
+FMB     ends
+FM      segment dword use32 public 'DATA'
+FM      ends
+FME     segment dword use32 public 'DATA'
+FME     ends
+
+; This leaves room in the _fatexit() list for _moduleDtor()
+XOB     segment dword use32 public 'BSS'
+XOB     ends
+XO      segment dword use32 public 'BSS'
+    dd  ?
+XO      ends
+XOE     segment dword use32 public 'BSS'
+XOE     ends
+
+DGROUP         group   FMB,FM,FME
+
+    begcode minit
+
+; extern (C) void _minit();
+; Converts array of ModuleInfo pointers to a D dynamic array of them,
+; so they can be accessed via D.
+; Result is written to:
+; extern (C) ModuleInfo[] _moduleinfo_array;
+
+    public  __minit
+__minit proc    near
+    mov EDX,offset DATAGRP:FMB
+    mov EAX,offset DATAGRP:FME
+    mov dword ptr __moduleinfo_array+4,EDX
+    sub EAX,EDX         ; size in bytes of FM segment
+    shr EAX,2           ; convert to array length
+    mov dword ptr __moduleinfo_array,EAX
+    ret
+__minit endp
+
+    endcode minit
+
+    end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/monitor.c	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,215 @@
+/**
+ * Contains the implementation for object monitors.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if _WIN32
+#elif linux || __APPLE__
+#define USE_PTHREADS    1
+#else
+#endif
+
+#if _WIN32
+#include <windows.h>
+#endif
+
+#if USE_PTHREADS
+#include <pthread.h>
+#endif
+
+#include "mars.h"
+
+// This is what the monitor reference in Object points to
+typedef struct Monitor
+{
+    void* impl; // for user-level monitors
+    Array devt; // for internal monitors
+
+#if _WIN32
+    CRITICAL_SECTION mon;
+#endif
+
+#if USE_PTHREADS
+    pthread_mutex_t mon;
+#endif
+} Monitor;
+
+#define MONPTR(h)       (&((Monitor *)(h)->monitor)->mon)
+
+static volatile int inited;
+
+/* =============================== Win32 ============================ */
+
+#if _WIN32
+
+static CRITICAL_SECTION _monitor_critsec;
+
+void _STI_monitor_staticctor()
+{
+    if (!inited)
+    {   InitializeCriticalSection(&_monitor_critsec);
+        inited = 1;
+    }
+}
+
+void _STD_monitor_staticdtor()
+{
+    if (inited)
+    {   inited = 0;
+        DeleteCriticalSection(&_monitor_critsec);
+    }
+}
+
+void _d_monitor_create(Object *h)
+{
+    /*
+     * NOTE: Assume this is only called when h->monitor is null prior to the
+     * call.  However, please note that another thread may call this function
+     * at the same time, so we can not assert this here.  Instead, try and
+     * create a lock, and if one already exists then forget about it.
+     */
+
+    //printf("+_d_monitor_create(%p)\n", h);
+    assert(h);
+    Monitor *cs = NULL;
+    EnterCriticalSection(&_monitor_critsec);
+    if (!h->monitor)
+    {
+        cs = (Monitor *)calloc(sizeof(Monitor), 1);
+        assert(cs);
+        InitializeCriticalSection(&cs->mon);
+        h->monitor = (void *)cs;
+        cs = NULL;
+    }
+    LeaveCriticalSection(&_monitor_critsec);
+    if (cs)
+        free(cs);
+    //printf("-_d_monitor_create(%p)\n", h);
+}
+
+void _d_monitor_destroy(Object *h)
+{
+    //printf("+_d_monitor_destroy(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    DeleteCriticalSection(MONPTR(h));
+    free((void *)h->monitor);
+    h->monitor = NULL;
+    //printf("-_d_monitor_destroy(%p)\n", h);
+}
+
+int _d_monitor_lock(Object *h)
+{
+    //printf("+_d_monitor_acquire(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    EnterCriticalSection(MONPTR(h));
+    //printf("-_d_monitor_acquire(%p)\n", h);
+}
+
+void _d_monitor_unlock(Object *h)
+{
+    //printf("+_d_monitor_release(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    LeaveCriticalSection(MONPTR(h));
+    //printf("-_d_monitor_release(%p)\n", h);
+}
+
+#endif
+
+/* =============================== linux ============================ */
+
+#if USE_PTHREADS
+
+#ifndef PTHREAD_MUTEX_RECURSIVE
+#    define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
+#endif
+
+// Includes attribute fixes from David Friedman's GDC port
+
+static pthread_mutex_t _monitor_critsec;
+static pthread_mutexattr_t _monitors_attr;
+
+void _STI_monitor_staticctor()
+{
+    if (!inited)
+    {
+        pthread_mutexattr_init(&_monitors_attr);
+        pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE);
+        pthread_mutex_init(&_monitor_critsec, 0);
+        inited = 1;
+    }
+}
+
+void _STD_monitor_staticdtor()
+{
+    if (inited)
+    {   inited = 0;
+        pthread_mutex_destroy(&_monitor_critsec);
+        pthread_mutexattr_destroy(&_monitors_attr);
+    }
+}
+
+void _d_monitor_create(Object *h)
+{
+    /*
+     * NOTE: Assume this is only called when h->monitor is null prior to the
+     * call.  However, please note that another thread may call this function
+     * at the same time, so we can not assert this here.  Instead, try and
+     * create a lock, and if one already exists then forget about it.
+     */
+
+    //printf("+_d_monitor_create(%p)\n", h);
+    assert(h);
+    Monitor *cs = NULL;
+    pthread_mutex_lock(&_monitor_critsec);
+    if (!h->monitor)
+    {
+        cs = (Monitor *)calloc(sizeof(Monitor), 1);
+        assert(cs);
+        pthread_mutex_init(&cs->mon, & _monitors_attr);
+        h->monitor = (void *)cs;
+        cs = NULL;
+    }
+    pthread_mutex_unlock(&_monitor_critsec);
+    if (cs)
+        free(cs);
+    //printf("-_d_monitor_create(%p)\n", h);
+}
+
+void _d_monitor_destroy(Object *h)
+{
+    //printf("+_d_monitor_destroy(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_destroy(MONPTR(h));
+    free((void *)h->monitor);
+    h->monitor = NULL;
+    //printf("-_d_monitor_destroy(%p)\n", h);
+}
+
+int _d_monitor_lock(Object *h)
+{
+    //printf("+_d_monitor_acquire(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_lock(MONPTR(h));
+    //printf("-_d_monitor_acquire(%p)\n", h);
+}
+
+void _d_monitor_unlock(Object *h)
+{
+    //printf("+_d_monitor_release(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_unlock(MONPTR(h));
+    //printf("-_d_monitor_release(%p)\n", h);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/obj.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,34 @@
+/**
+ * Containts object comparator functions called by generated code.
+ *
+ * Copyright: Copyright Digital Mars 2002 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.obj;
+
+extern (C):
+
+/********************************
+ * Compiler helper for operator == for class objects.
+ */
+
+int _d_obj_eq(Object o1, Object o2)
+{
+    return o1 is o2 || (o1 && o1.opEquals(o2));
+}
+
+
+/********************************
+ * Compiler helper for operator <, <=, >, >= for class objects.
+ */
+
+int _d_obj_cmp(Object o1, Object o2)
+{
+    return o1.opCmp(o2);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/posix.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,82 @@
+# Makefile to build the compiler runtime D library for Linux
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR=../../../lib
+DOCDIR=../../../doc
+IMPDIR=../../../import
+LIBBASENAME=libdruntime-rt-dmd.a
+MODULES=
+BUILDS=debug release unittest
+
+MODULES_BASE=aaA aApply aApplyR adi alloca arrayassign arraybyte	\
+    arraycast arraycat arraydouble arrayfloat arrayint arrayreal	\
+    arrayshort cast_ cmath2 cover deh2 dmain2 invariant invariant_	\
+    lifetime llmath memory memset obj object_ qsort switch_ trace
+# NOTE: trace.o and cover.o are not necessary for a successful build
+#       as both are used for debugging features (profiling and coverage)
+# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and
+#       minit.asm is not used by dmd for Linux
+# NOTE: deh.o is only needed for Win32, Linux uses deh2.o
+MODULES_UTIL=$(addprefix util/,console cpuid ctype string utf)
+MODULES_TI=$(addprefix typeinfo/ti_,AC Acdouble Acfloat Acreal Adouble	\
+    Afloat Ag Aint Along Areal Ashort byte C cdouble cfloat char creal	\
+    dchar delegate double float idouble ifloat int ireal long ptr real	\
+    short ubyte uint ulong ushort void wchar)
+C_SRCS=complex.c critical.c memory_osx.c monitor.c
+
+# Symbols
+
+DMD=dmd
+DOCFLAGS=-version=DDoc
+DFLAGS_release=-d -release -O -inline -w -nofloat
+DFLAGS_debug=-d -g -w -nofloat
+DFLAGS_unittest=$(DFLAGS_release) -unittest
+CFLAGS_release=-m32 -O
+CFLAGS_debug=-m32 -g
+CFLAGS_unittest=$(CFLAGS_release)
+
+# Derived symbols
+
+C_OBJS=$(addsuffix .o,$(basename $(C_SRCS)))
+AS_OBJS=$(addsuffix .o,$(basename $(AS_SRCS)))
+ALL_MODULES=$(MODULES_BASE) $(MODULES_UTIL) $(MODULES_TI)
+D_SRCS=$(addsuffix .d,$(ALL_MODULES))
+ALLLIBS=$(addsuffix /$(LIBBASENAME),$(addprefix $(LIBDIR)/,$(BUILDS)))
+
+# Patterns
+
+$(LIBDIR)/%/$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_SRCS)
+	$(CC) -c $(CFLAGS_$*) $(C_SRCS)
+	$(DMD) $(DFLAGS_$*) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS)
+	rm $(C_OBJS) $(AS_OBJS)
+
+$(DOCDIR)/%.html : %.d
+	$(DMD) -c -d -o- -Df$@ $<
+
+$(IMPDIR)/%.di : %.d
+	$(DMD) -c -d -o- -Hf$@ $<
+
+# Rulez
+
+all : $(BUILDS) doc
+
+debug : $(LIBDIR)/debug/$(LIBBASENAME) $(IMPORTS)
+release : $(LIBDIR)/release/$(LIBBASENAME) $(IMPORTS)
+unittest : $(LIBDIR)/unittest/$(LIBBASENAME) $(IMPORTS)
+#doc : $(DOCS)
+
+clean :
+	rm -f $(IMPORTS) $(DOCS) $(ALLLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/qsort.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,158 @@
+/*
+        Portions of this file are:
+        Copyright Prototronics, 1987
+        Totem Lake P.O. 8117
+        Kirkland, Washington 98034
+        (206) 820-1972
+        Licensed to Digital Mars.
+
+        June 11, 1987 from Ray Gardner's
+        Denver, Colorado) public domain version
+
+        Use qsort2.d instead of this file if a redistributable version of
+        _adSort() is required.
+*/
+
+module rt.qsort;
+
+/*
+**    Sorts an array starting at base, of length nbr_elements, each
+**    element of size width_bytes, ordered via compare_function; which
+**    is called as  (*comp_fp)(ptr_to_element1, ptr_to_element2)
+**    and returns < 0 if element1 < element2, 0 if element1 = element2,
+**    > 0 if element1 > element2.  Most of the refinements are due to
+**    R. Sedgewick.  See "Implementing Quicksort Programs", Comm. ACM,
+**    Oct. 1978, and Corrigendum, Comm. ACM, June 1979.
+*/
+
+//debug=qsort;          // uncomment to turn on debugging printf's
+
+
+struct Array
+{
+    size_t length;
+    void*  ptr;
+}
+
+
+private const int _maxspan = 7; // subarrays of _maxspan or fewer elements
+                                // will be sorted by a simple insertion sort
+
+/* Adjust _maxspan according to relative cost of a swap and a compare.  Reduce
+_maxspan (not less than 1) if a swap is very expensive such as when you have
+an array of large structures to be sorted, rather than an array of pointers to
+structures.  The default value is optimized for a high cost for compares. */
+
+
+extern (C) long _adSort(Array a, TypeInfo ti)
+{
+  byte* base;
+  byte*[40] stack;              // stack
+  byte** sp;                    // stack pointer
+  byte* i, j, limit;            // scan and limit pointers
+  uint thresh;                  // size of _maxspan elements in bytes
+  uint width = ti.tsize();
+
+  base = cast(byte *)a.ptr;
+  thresh = _maxspan * width;             // init threshold
+  sp = stack.ptr;                        // init stack pointer
+  limit = base + a.length * width;       // pointer past end of array
+  while (1)                              // repeat until done then return
+  {
+    while (limit - base > thresh)        // if more than _maxspan elements
+    {
+      //swap middle, base
+      ti.swap((cast(uint)(limit - base) >> 1) -
+           (((cast(uint)(limit - base) >> 1)) % width) + base, base);
+
+      i = base + width;                 // i scans from left to right
+      j = limit - width;                // j scans from right to left
+
+      if (ti.compare(i, j) > 0)         // Sedgewick's
+        ti.swap(i, j);                  //    three-element sort
+      if (ti.compare(base, j) > 0)      // sets things up
+        ti.swap(base, j);               // so that
+      if (ti.compare(i, base) > 0)      // *i <= *base <= *j
+        ti.swap(i, base);               // *base is the pivot element
+
+      while (1)
+      {
+        do                              // move i right until *i >= pivot
+          i += width;
+        while (ti.compare(i, base) < 0);
+        do                              // move j left until *j <= pivot
+          j -= width;
+        while (ti.compare(j, base) > 0);
+        if (i > j)                      // break loop if pointers crossed
+          break;
+        ti.swap(i, j);                  // else swap elements, keep scanning
+      }
+      ti.swap(base, j);                 // move pivot into correct place
+      if (j - base > limit - i)         // if left subarray is larger...
+      {
+        sp[0] = base;                   // stack left subarray base
+        sp[1] = j;                      //    and limit
+        base = i;                       // sort the right subarray
+      }
+      else                              // else right subarray is larger
+      {
+        sp[0] = i;                      // stack right subarray base
+        sp[1] = limit;                  //    and limit
+        limit = j;                      // sort the left subarray
+      }
+      sp += 2;                          // increment stack pointer
+      assert(sp < cast(byte**)stack + stack.length);
+    }
+
+    // Insertion sort on remaining subarray
+    i = base + width;
+    while (i < limit)
+    {
+      j = i;
+      while (j > base && ti.compare(j - width, j) > 0)
+      {
+        ti.swap(j - width, j);
+        j -= width;
+      }
+      i += width;
+    }
+
+    if (sp > stack.ptr)                 // if any entries on stack...
+    {
+      sp -= 2;                          // pop the base and limit
+      base = sp[0];
+      limit = sp[1];
+    }
+    else                                // else stack empty, all done
+      return *cast(long*)(&a);
+  }
+  assert(0);
+}
+
+
+unittest
+{
+    debug(qsort) printf("array.sort.unittest()\n");
+
+    int a[] = new int[10];
+
+    a[0] = 23;
+    a[1] = 1;
+    a[2] = 64;
+    a[3] = 5;
+    a[4] = 6;
+    a[5] = 5;
+    a[6] = 17;
+    a[7] = 3;
+    a[8] = 0;
+    a[9] = -1;
+
+    a.sort;
+
+    for (int i = 0; i < a.length - 1; i++)
+    {
+        //printf("i = %d", i);
+        //printf(" %d %d\n", a[i], a[i + 1]);
+        assert(a[i] <= a[i + 1]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/qsort2.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,71 @@
+/**
+ * This is a public domain version of qsort.d.  All it does is call C's
+ * qsort(), but runs a little slower since it needs to synchronize a global
+ * variable.
+ *
+ * Copyright: Copyright Digital Mars 2000 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2000 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.qsort2;
+
+//debug=qsort;
+
+private import core.stdc.stdlib;
+
+struct Array
+{
+    size_t length;
+    void*  ptr;
+}
+
+private TypeInfo tiglobal;
+
+extern (C) int cmp(void* p1, void* p2)
+{
+    return tiglobal.compare(p1, p2);
+}
+
+extern (C) long _adSort(Array a, TypeInfo ti)
+{
+    synchronized
+    {
+        tiglobal = ti;
+        qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp);
+    }
+    return *cast(long*)(&a);
+}
+
+
+
+unittest
+{
+    debug(qsort) printf("array.sort.unittest()\n");
+
+    int a[] = new int[10];
+
+    a[0] = 23;
+    a[1] = 1;
+    a[2] = 64;
+    a[3] = 5;
+    a[4] = 6;
+    a[5] = 5;
+    a[6] = 17;
+    a[7] = 3;
+    a[8] = 0;
+    a[9] = -1;
+
+    a.sort;
+
+    for (int i = 0; i < a.length - 1; i++)
+    {
+        //printf("i = %d", i);
+        //printf(" %d %d\n", a[i], a[i + 1]);
+        assert(a[i] <= a[i + 1]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/switch_.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,411 @@
+/**
+ * Contains support code for switch blocks using string constants.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.switch_;
+
+private import core.stdc.string;
+
+/******************************************************
+ * Support for switch statements switching on strings.
+ * Input:
+ *      table[]         sorted array of strings generated by compiler
+ *      ca              string to look up in table
+ * Output:
+ *      result          index of match in table[]
+ *                      -1 if not in table
+ */
+
+extern (C):
+
+int _d_switch_string(char[][] table, char[] ca)
+in
+{
+    //printf("in _d_switch_string()\n");
+    assert(table.length >= 0);
+    assert(ca.length >= 0);
+
+    // Make sure table[] is sorted correctly
+    int j;
+
+    for (j = 1; j < table.length; j++)
+    {
+        int len1 = table[j - 1].length;
+        int len2 = table[j].length;
+
+        assert(len1 <= len2);
+        if (len1 == len2)
+        {
+            int ci;
+
+            ci = memcmp(table[j - 1].ptr, table[j].ptr, len1);
+            assert(ci < 0); // ci==0 means a duplicate
+        }
+    }
+}
+out (result)
+{
+    int i;
+    int cj;
+
+    //printf("out _d_switch_string()\n");
+    if (result == -1)
+    {
+        // Not found
+        for (i = 0; i < table.length; i++)
+        {
+            if (table[i].length == ca.length)
+            {   cj = memcmp(table[i].ptr, ca.ptr, ca.length);
+                assert(cj != 0);
+            }
+        }
+    }
+    else
+    {
+        assert(0 <= result && result < table.length);
+        for (i = 0; 1; i++)
+        {
+            assert(i < table.length);
+            if (table[i].length == ca.length)
+            {
+                cj = memcmp(table[i].ptr, ca.ptr, ca.length);
+                if (cj == 0)
+                {
+                    assert(i == result);
+                    break;
+                }
+            }
+        }
+    }
+}
+body
+{
+    //printf("body _d_switch_string(%.*s)\n", ca);
+    int low;
+    int high;
+    int mid;
+    int c;
+    char[] pca;
+
+    low = 0;
+    high = table.length;
+
+    version (none)
+    {
+        // Print table
+        printf("ca[] = '%s'\n", cast(char *)ca);
+        for (mid = 0; mid < high; mid++)
+        {
+            pca = table[mid];
+            printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
+        }
+    }
+    if (high &&
+        ca.length >= table[0].length &&
+        ca.length <= table[high - 1].length)
+    {
+        // Looking for 0 length string, which would only be at the beginning
+        if (ca.length == 0)
+            return 0;
+
+        char c1 = ca[0];
+
+        // Do binary search
+        while (low < high)
+        {
+            mid = (low + high) >> 1;
+            pca = table[mid];
+            c = ca.length - pca.length;
+            if (c == 0)
+            {
+                c = cast(ubyte)c1 - cast(ubyte)pca[0];
+                if (c == 0)
+                {
+                    c = memcmp(ca.ptr, pca.ptr, ca.length);
+                    if (c == 0)
+                    {   //printf("found %d\n", mid);
+                        return mid;
+                    }
+                }
+            }
+            if (c < 0)
+            {
+                high = mid;
+            }
+            else
+            {
+                low = mid + 1;
+            }
+        }
+    }
+
+    //printf("not found\n");
+    return -1; // not found
+}
+
+unittest
+{
+    switch (cast(char []) "c")
+    {
+         case "coo":
+         default:
+             break;
+    }
+}
+
+/**********************************
+ * Same thing, but for wide chars.
+ */
+
+int _d_switch_ustring(wchar[][] table, wchar[] ca)
+in
+{
+    //printf("in _d_switch_ustring()\n");
+    assert(table.length >= 0);
+    assert(ca.length >= 0);
+
+    // Make sure table[] is sorted correctly
+    int j;
+
+    for (j = 1; j < table.length; j++)
+    {
+        int len1 = table[j - 1].length;
+        int len2 = table[j].length;
+
+        assert(len1 <= len2);
+        if (len1 == len2)
+        {
+            int c;
+
+            c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof);
+            assert(c < 0);  // c==0 means a duplicate
+        }
+    }
+}
+out (result)
+{
+    int i;
+    int c;
+
+    //printf("out _d_switch_string()\n");
+    if (result == -1)
+    {
+        // Not found
+        for (i = 0; i < table.length; i++)
+        {
+            if (table[i].length == ca.length)
+            {   c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
+                assert(c != 0);
+            }
+        }
+    }
+    else
+    {
+        assert(0 <= result && result < table.length);
+        for (i = 0; 1; i++)
+        {
+            assert(i < table.length);
+            if (table[i].length == ca.length)
+            {
+                c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
+                if (c == 0)
+                {
+                    assert(i == result);
+                    break;
+                }
+            }
+        }
+    }
+}
+body
+{
+    //printf("body _d_switch_ustring()\n");
+    int low;
+    int high;
+    int mid;
+    int c;
+    wchar[] pca;
+
+    low = 0;
+    high = table.length;
+
+/*
+    // Print table
+    wprintf("ca[] = '%.*s'\n", ca);
+    for (mid = 0; mid < high; mid++)
+    {
+        pca = table[mid];
+        wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
+    }
+*/
+
+    // Do binary search
+    while (low < high)
+    {
+        mid = (low + high) >> 1;
+        pca = table[mid];
+        c = ca.length - pca.length;
+        if (c == 0)
+        {
+            c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof);
+            if (c == 0)
+            {   //printf("found %d\n", mid);
+                return mid;
+            }
+        }
+        if (c < 0)
+        {
+            high = mid;
+        }
+        else
+        {
+            low = mid + 1;
+        }
+    }
+    //printf("not found\n");
+    return -1;              // not found
+}
+
+
+unittest
+{
+    switch (cast(wchar []) "c")
+    {
+         case "coo":
+         default:
+             break;
+    }
+}
+
+
+/**********************************
+ * Same thing, but for wide chars.
+ */
+
+int _d_switch_dstring(dchar[][] table, dchar[] ca)
+in
+{
+    //printf("in _d_switch_dstring()\n");
+    assert(table.length >= 0);
+    assert(ca.length >= 0);
+
+    // Make sure table[] is sorted correctly
+    int j;
+
+    for (j = 1; j < table.length; j++)
+    {
+        int len1 = table[j - 1].length;
+        int len2 = table[j].length;
+
+        assert(len1 <= len2);
+        if (len1 == len2)
+        {
+            int c;
+
+            c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof);
+            assert(c < 0);  // c==0 means a duplicate
+        }
+    }
+}
+out (result)
+{
+    int i;
+    int c;
+
+    //printf("out _d_switch_string()\n");
+    if (result == -1)
+    {
+        // Not found
+        for (i = 0; i < table.length; i++)
+        {
+            if (table[i].length == ca.length)
+            {   c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
+                assert(c != 0);
+            }
+        }
+    }
+    else
+    {
+        assert(0 <= result && result < table.length);
+        for (i = 0; 1; i++)
+        {
+            assert(i < table.length);
+            if (table[i].length == ca.length)
+            {
+                c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
+                if (c == 0)
+                {
+                    assert(i == result);
+                    break;
+                }
+            }
+        }
+    }
+}
+body
+{
+    //printf("body _d_switch_ustring()\n");
+    int low;
+    int high;
+    int mid;
+    int c;
+    dchar[] pca;
+
+    low = 0;
+    high = table.length;
+
+/*
+    // Print table
+    wprintf("ca[] = '%.*s'\n", ca);
+    for (mid = 0; mid < high; mid++)
+    {
+        pca = table[mid];
+        wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
+    }
+*/
+
+    // Do binary search
+    while (low < high)
+    {
+        mid = (low + high) >> 1;
+        pca = table[mid];
+        c = ca.length - pca.length;
+        if (c == 0)
+        {
+            c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof);
+            if (c == 0)
+            {   //printf("found %d\n", mid);
+                return mid;
+            }
+        }
+        if (c < 0)
+        {
+            high = mid;
+        }
+        else
+        {
+            low = mid + 1;
+        }
+    }
+    //printf("not found\n");
+    return -1; // not found
+}
+
+
+unittest
+{
+    switch (cast(dchar []) "c")
+    {
+         case "coo":
+         default:
+             break;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/tls.S	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,44 @@
+/**
+ * Contains support code for thread-local storage.
+ *
+ * Copyright: Copyright Digital Mars 2008 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2008 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+#if linux
+
+/* The memory between the addresses of _tlsstart and _tlsend is the storage for
+ * thread-local data in D 2.0.  Both of these rely on the default linker script
+ * of:
+ *      .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ *      .tbss  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ * to group the sections in that order.
+ *
+ * Sadly, this does not work because ld orders .tdata after .tdata.*, despite
+ * what the linker script says.
+ */
+
+.file "tls.S"
+
+.globl _tlsstart
+    .section .tdata,"awT",@progbits
+    .align 4
+    .type   _tlsstart, @object
+    .size   _tlsstart, 4
+_tlsstart:
+    .long   3
+
+.globl _tlsend
+    .section .tcommon,"awT",@nobits
+    .align 4
+    .type   _tlsend, @object
+    .size   _tlsend, 4
+_tlsend:
+    .zero   4
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/trace.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,919 @@
+/**
+ * Contains support code for code profiling.
+ *
+ * Copyright: Copyright Digital Mars 1995 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 1995 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.trace;
+
+private
+{
+    import rt.util.string;
+    import core.stdc.ctype;
+    import core.stdc.stdio;
+    import core.stdc.string;
+    import core.stdc.stdlib;
+}
+
+extern (C):
+
+char* unmangle_ident(char*);    // from DMC++ runtime library
+
+alias long timer_t;
+
+/////////////////////////////////////
+//
+
+struct SymPair
+{
+    SymPair* next;
+    Symbol* sym;        // function that is called
+    uint count;         // number of times sym is called
+}
+
+/////////////////////////////////////
+// A Symbol for each function name.
+
+struct Symbol
+{
+        Symbol* Sl, Sr;         // left, right children
+        SymPair* Sfanin;        // list of calling functions
+        SymPair* Sfanout;       // list of called functions
+        timer_t totaltime;      // aggregate time
+        timer_t functime;       // time excluding subfunction calls
+        ubyte Sflags;
+        char[] Sident;          // name of symbol
+}
+
+const ubyte SFvisited = 1;      // visited
+
+
+//////////////////////////////////
+// Build a linked list of these.
+
+struct Stack
+{
+    Stack* prev;
+    Symbol* sym;
+    timer_t starttime;          // time when function was entered
+    timer_t ohd;                // overhead of all the bookkeeping code
+    timer_t subtime;            // time used by all subfunctions
+}
+
+__gshared			// doesn't work with multithreaded code anyway
+{
+    Symbol* root;            // root of symbol table
+
+    Stack* stack_freelist;
+    Stack* trace_tos;                // top of stack
+    int trace_inited;                // !=0 if initialized
+    timer_t trace_ohd;
+
+    Symbol** psymbols;
+    uint nsymbols;           // number of symbols
+
+    string trace_logfilename = "trace.log";
+    FILE* fplog;
+
+    string trace_deffilename = "trace.def";
+    FILE* fpdef;
+}
+
+////////////////////////////////////////
+// Set file name for output.
+// A file name of "" means write results to stdout.
+// Returns:
+//      0       success
+//      !=0     failure
+
+int trace_setlogfilename(string name)
+{
+    trace_logfilename = name;
+    return 0;
+}
+
+////////////////////////////////////////
+// Set file name for output.
+// A file name of "" means write results to stdout.
+// Returns:
+//      0       success
+//      !=0     failure
+
+int trace_setdeffilename(string name)
+{
+    trace_deffilename = name;
+    return 0;
+}
+
+////////////////////////////////////////
+// Output optimal function link order.
+
+static void trace_order(Symbol *s)
+{
+    while (s)
+    {
+        trace_place(s,0);
+        if (s.Sl)
+            trace_order(s.Sl);
+        s = s.Sr;
+    }
+}
+
+//////////////////////////////////////////////
+//
+
+static Stack* stack_malloc()
+{   Stack *s;
+
+    if (stack_freelist)
+    {   s = stack_freelist;
+        stack_freelist = s.prev;
+    }
+    else
+        s = cast(Stack *)trace_malloc(Stack.sizeof);
+    return s;
+}
+
+//////////////////////////////////////////////
+//
+
+static void stack_free(Stack *s)
+{
+    s.prev = stack_freelist;
+    stack_freelist = s;
+}
+
+//////////////////////////////////////
+// Qsort() comparison routine for array of pointers to SymPair's.
+
+static int sympair_cmp(in void* e1, in void* e2)
+{   SymPair** psp1;
+    SymPair** psp2;
+
+    psp1 = cast(SymPair**)e1;
+    psp2 = cast(SymPair**)e2;
+
+    return (*psp2).count - (*psp1).count;
+}
+
+//////////////////////////////////////
+// Place symbol s, and then place any fan ins or fan outs with
+// counts greater than count.
+
+static void trace_place(Symbol *s, uint count)
+{   SymPair* sp;
+    SymPair** base;
+
+    if (!(s.Sflags & SFvisited))
+    {   size_t num;
+        uint u;
+
+        //printf("\t%.*s\t%u\n", s.Sident, count);
+        fprintf(fpdef,"\t%.*s\n", s.Sident);
+        s.Sflags |= SFvisited;
+
+        // Compute number of items in array
+        num = 0;
+        for (sp = s.Sfanin; sp; sp = sp.next)
+            num++;
+        for (sp = s.Sfanout; sp; sp = sp.next)
+            num++;
+        if (!num)
+            return;
+
+        // Allocate and fill array
+        base = cast(SymPair**)trace_malloc(SymPair.sizeof * num);
+        u = 0;
+        for (sp = s.Sfanin; sp; sp = sp.next)
+            base[u++] = sp;
+        for (sp = s.Sfanout; sp; sp = sp.next)
+            base[u++] = sp;
+
+        // Sort array
+        qsort(base, num, (SymPair *).sizeof, &sympair_cmp);
+
+        //for (u = 0; u < num; u++)
+            //printf("\t\t%.*s\t%u\n", base[u].sym.Sident, base[u].count);
+
+        // Place symbols
+        for (u = 0; u < num; u++)
+        {
+            if (base[u].count >= count)
+            {   uint u2;
+                uint c2;
+
+                u2 = (u + 1 < num) ? u + 1 : u;
+                c2 = base[u2].count;
+                if (c2 < count)
+                    c2 = count;
+                trace_place(base[u].sym,c2);
+            }
+            else
+                break;
+        }
+
+        // Clean up
+        trace_free(base);
+    }
+}
+
+/////////////////////////////////////
+// Initialize and terminate.
+
+static this()
+{
+    trace_init();
+}
+
+static ~this()
+{
+    trace_term();
+}
+
+///////////////////////////////////
+// Report results.
+// Also compute nsymbols.
+
+static void trace_report(Symbol* s)
+{   SymPair* sp;
+    uint count;
+
+    //printf("trace_report()\n");
+    while (s)
+    {   nsymbols++;
+        if (s.Sl)
+            trace_report(s.Sl);
+        fprintf(fplog,"------------------\n");
+        count = 0;
+        for (sp = s.Sfanin; sp; sp = sp.next)
+        {
+            fprintf(fplog,"\t%5d\t%.*s\n", sp.count, sp.sym.Sident);
+            count += sp.count;
+        }
+        fprintf(fplog,"%.*s\t%u\t%lld\t%lld\n",s.Sident,count,s.totaltime,s.functime);
+        for (sp = s.Sfanout; sp; sp = sp.next)
+        {
+            fprintf(fplog,"\t%5d\t%.*s\n",sp.count,sp.sym.Sident);
+        }
+        s = s.Sr;
+    }
+}
+
+////////////////////////////////////
+// Allocate and fill array of symbols.
+
+static void trace_array(Symbol *s)
+{
+    __gshared uint u;
+
+    if (!psymbols)
+    {   u = 0;
+        psymbols = cast(Symbol **)trace_malloc((Symbol *).sizeof * nsymbols);
+    }
+    while (s)
+    {
+        psymbols[u++] = s;
+        trace_array(s.Sl);
+        s = s.Sr;
+    }
+}
+
+
+//////////////////////////////////////
+// Qsort() comparison routine for array of pointers to Symbol's.
+
+static int symbol_cmp(in void* e1, in void* e2)
+{   Symbol** ps1;
+    Symbol** ps2;
+    timer_t diff;
+
+    ps1 = cast(Symbol **)e1;
+    ps2 = cast(Symbol **)e2;
+
+    diff = (*ps2).functime - (*ps1).functime;
+    return (diff == 0) ? 0 : ((diff > 0) ? 1 : -1);
+}
+
+
+///////////////////////////////////
+// Report function timings
+
+static void trace_times(Symbol* root)
+{   uint u;
+    timer_t freq;
+
+    // Sort array
+    qsort(psymbols, nsymbols, (Symbol *).sizeof, &symbol_cmp);
+
+    // Print array
+    QueryPerformanceFrequency(&freq);
+    fprintf(fplog,"\n======== Timer Is %lld Ticks/Sec, Times are in Microsecs ========\n\n",freq);
+    fprintf(fplog,"  Num          Tree        Func        Per\n");
+    fprintf(fplog,"  Calls        Time        Time        Call\n\n");
+    for (u = 0; u < nsymbols; u++)
+    {   Symbol* s = psymbols[u];
+        timer_t tl,tr;
+        timer_t fl,fr;
+        timer_t pl,pr;
+        timer_t percall;
+        SymPair* sp;
+        uint calls;
+        char[] id;
+
+        version (Windows)
+        {
+            char* p = (s.Sident ~ '\0').ptr;
+            p = unmangle_ident(p);
+            if (p)
+                id = p[0 .. strlen(p)];
+        }
+        if (!id)
+            id = s.Sident;
+        calls = 0;
+        for (sp = s.Sfanin; sp; sp = sp.next)
+            calls += sp.count;
+        if (calls == 0)
+            calls = 1;
+
+version (all)
+{
+        tl = (s.totaltime * 1000000) / freq;
+        fl = (s.functime  * 1000000) / freq;
+        percall = s.functime / calls;
+        pl = (s.functime * 1000000) / calls / freq;
+
+        fprintf(fplog,"%7d%12lld%12lld%12lld     %.*s\n",
+            calls,tl,fl,pl,id);
+}
+else
+{
+        tl = s.totaltime / freq;
+        tr = ((s.totaltime - tl * freq) * 10000000) / freq;
+
+        fl = s.functime  / freq;
+        fr = ((s.functime  - fl * freq) * 10000000) / freq;
+
+        percall = s.functime / calls;
+        pl = percall  / freq;
+        pr = ((percall  - pl * freq) * 10000000) / freq;
+
+        fprintf(fplog,"%7d\t%3lld.%07lld\t%3lld.%07lld\t%3lld.%07lld\t%.*s\n",
+            calls,tl,tr,fl,fr,pl,pr,id);
+}
+        if (id !is s.Sident)
+            free(id.ptr);
+    }
+}
+
+
+///////////////////////////////////
+// Initialize.
+
+static void trace_init()
+{
+    if (!trace_inited)
+    {
+        trace_inited = 1;
+
+        {   // See if we can determine the overhead.
+            uint u;
+            timer_t starttime;
+            timer_t endtime;
+            Stack *st;
+
+            st = trace_tos;
+            trace_tos = null;
+            QueryPerformanceCounter(&starttime);
+            for (u = 0; u < 100; u++)
+            {
+                asm
+                {
+                    call _trace_pro_n   ;
+                    db   0              ;
+                    call _trace_epi_n   ;
+                }
+            }
+            QueryPerformanceCounter(&endtime);
+            trace_ohd = (endtime - starttime) / u;
+            //printf("trace_ohd = %lld\n",trace_ohd);
+            if (trace_ohd > 0)
+                trace_ohd--;            // round down
+            trace_tos = st;
+        }
+    }
+}
+
+/////////////////////////////////
+// Terminate.
+
+void trace_term()
+{
+    //printf("trace_term()\n");
+    if (trace_inited == 1)
+    {   Stack *n;
+
+        trace_inited = 2;
+
+        // Free remainder of the stack
+        while (trace_tos)
+        {
+            n = trace_tos.prev;
+            stack_free(trace_tos);
+            trace_tos = n;
+        }
+
+        while (stack_freelist)
+        {
+            n = stack_freelist.prev;
+            stack_free(stack_freelist);
+            stack_freelist = n;
+        }
+
+        // Merge in data from any existing file
+        trace_merge();
+
+        // Report results
+        fplog = fopen(trace_logfilename.ptr, "w");
+        if (fplog)
+        {   nsymbols = 0;
+            trace_report(root);
+            trace_array(root);
+            trace_times(root);
+            fclose(fplog);
+        }
+
+        // Output function link order
+        fpdef = fopen(trace_deffilename.ptr,"w");
+        if (fpdef)
+        {   fprintf(fpdef,"\nFUNCTIONS\n");
+            trace_order(root);
+            fclose(fpdef);
+        }
+
+        trace_free(psymbols);
+        psymbols = null;
+    }
+}
+
+/////////////////////////////////
+// Our storage allocator.
+
+static void *trace_malloc(size_t nbytes)
+{   void *p;
+
+    p = malloc(nbytes);
+    if (!p)
+        exit(EXIT_FAILURE);
+    return p;
+}
+
+static void trace_free(void *p)
+{
+    free(p);
+}
+
+//////////////////////////////////////////////
+//
+
+static Symbol* trace_addsym(char[] id)
+{
+    Symbol** parent;
+    Symbol* rover;
+    Symbol* s;
+    int cmp;
+    char c;
+
+    //printf("trace_addsym('%s',%d)\n",p,len);
+    parent = &root;
+    rover = *parent;
+    while (rover !is null)               // while we haven't run out of tree
+    {
+        cmp = dstrcmp(id, rover.Sident);
+        if (cmp == 0)
+        {
+            return rover;
+        }
+        parent = (cmp < 0) ?            /* if we go down left side      */
+            &(rover.Sl) :               /* then get left child          */
+            &(rover.Sr);                /* else get right child         */
+        rover = *parent;                /* get child                    */
+    }
+    /* not in table, so insert into table       */
+    s = cast(Symbol *)trace_malloc(Symbol.sizeof);
+    memset(s,0,Symbol.sizeof);
+    s.Sident = id;
+    *parent = s;                        // link new symbol into tree
+    return s;
+}
+
+/***********************************
+ * Add symbol s with count to SymPair list.
+ */
+
+static void trace_sympair_add(SymPair** psp, Symbol* s, uint count)
+{   SymPair* sp;
+
+    for (; 1; psp = &sp.next)
+    {
+        sp = *psp;
+        if (!sp)
+        {
+            sp = cast(SymPair *)trace_malloc(SymPair.sizeof);
+            sp.sym = s;
+            sp.count = 0;
+            sp.next = null;
+            *psp = sp;
+            break;
+        }
+        else if (sp.sym == s)
+        {
+            break;
+        }
+    }
+    sp.count += count;
+}
+
+//////////////////////////////////////////////
+//
+
+static void trace_pro(char[] id)
+{
+    Stack* n;
+    Symbol* s;
+    timer_t starttime;
+    timer_t t;
+
+    QueryPerformanceCounter(&starttime);
+    if (id.length == 0)
+        return;
+    if (!trace_inited)
+        trace_init();                   // initialize package
+    n = stack_malloc();
+    n.prev = trace_tos;
+    trace_tos = n;
+    s = trace_addsym(id);
+    trace_tos.sym = s;
+    if (trace_tos.prev)
+    {
+        Symbol* prev;
+        int i;
+
+        // Accumulate Sfanout and Sfanin
+        prev = trace_tos.prev.sym;
+        trace_sympair_add(&prev.Sfanout,s,1);
+        trace_sympair_add(&s.Sfanin,prev,1);
+    }
+    QueryPerformanceCounter(&t);
+    trace_tos.starttime = starttime;
+    trace_tos.ohd = trace_ohd + t - starttime;
+    trace_tos.subtime = 0;
+    //printf("trace_tos.ohd=%lld, trace_ohd=%lld + t=%lld - starttime=%lld\n",
+    //  trace_tos.ohd,trace_ohd,t,starttime);
+}
+
+/////////////////////////////////////////
+//
+
+static void trace_epi()
+{   Stack* n;
+    timer_t endtime;
+    timer_t t;
+    timer_t ohd;
+
+    //printf("trace_epi()\n");
+    if (trace_tos)
+    {
+        timer_t starttime;
+        timer_t totaltime;
+
+        QueryPerformanceCounter(&endtime);
+        starttime = trace_tos.starttime;
+        totaltime = endtime - starttime - trace_tos.ohd;
+        if (totaltime < 0)
+        {   //printf("endtime=%lld - starttime=%lld - trace_tos.ohd=%lld < 0\n",
+            //  endtime,starttime,trace_tos.ohd);
+            totaltime = 0;              // round off error, just make it 0
+        }
+
+        // totaltime is time spent in this function + all time spent in
+        // subfunctions - bookkeeping overhead.
+        trace_tos.sym.totaltime += totaltime;
+
+        //if (totaltime < trace_tos.subtime)
+        //printf("totaltime=%lld < trace_tos.subtime=%lld\n",totaltime,trace_tos.subtime);
+        trace_tos.sym.functime  += totaltime - trace_tos.subtime;
+        ohd = trace_tos.ohd;
+        n = trace_tos.prev;
+        stack_free(trace_tos);
+        trace_tos = n;
+        if (n)
+        {   QueryPerformanceCounter(&t);
+            n.ohd += ohd + t - endtime;
+            n.subtime += totaltime;
+            //printf("n.ohd = %lld\n",n.ohd);
+        }
+    }
+}
+
+
+////////////////////////// FILE INTERFACE /////////////////////////
+
+/////////////////////////////////////
+// Read line from file fp.
+// Returns:
+//      trace_malloc'd line buffer
+//      null if end of file
+
+static char* trace_readline(FILE* fp)
+{   int c;
+    int dim;
+    int i;
+    char *buf;
+
+    //printf("trace_readline(%p)\n", fp);
+    i = 0;
+    dim = 0;
+    buf = null;
+    while (1)
+    {
+        if (i == dim)
+        {   char *p;
+
+            dim += 80;
+            p = cast(char *)trace_malloc(dim);
+            memcpy(p,buf,i);
+            trace_free(buf);
+            buf = p;
+        }
+        c = fgetc(fp);
+        switch (c)
+        {
+            case EOF:
+                if (i == 0)
+                {   trace_free(buf);
+                    return null;
+                }
+            case '\n':
+                goto L1;
+            default:
+                break;
+        }
+        buf[i] = cast(char)c;
+        i++;
+    }
+L1:
+    buf[i] = 0;
+    //printf("line '%s'\n",buf);
+    return buf;
+}
+
+//////////////////////////////////////
+// Skip space
+
+static char *skipspace(char *p)
+{
+    while (isspace(*p))
+        p++;
+    return p;
+}
+
+////////////////////////////////////////////////////////
+// Merge in profiling data from existing file.
+
+static void trace_merge()
+{   FILE *fp;
+    char *buf;
+    char *p;
+    uint count;
+    Symbol *s;
+    SymPair *sfanin;
+    SymPair **psp;
+
+    if (trace_logfilename && (fp = fopen(trace_logfilename.ptr,"r")) !is null)
+    {
+        buf = null;
+        sfanin = null;
+        psp = &sfanin;
+        while (1)
+        {
+            trace_free(buf);
+            buf = trace_readline(fp);
+            if (!buf)
+                break;
+            switch (*buf)
+            {
+                case '=':               // ignore rest of file
+                    trace_free(buf);
+                    goto L1;
+                case ' ':
+                case '\t':              // fan in or fan out line
+                    count = strtoul(buf,&p,10);
+                    if (p == buf)       // if invalid conversion
+                        continue;
+                    p = skipspace(p);
+                    if (!*p)
+                        continue;
+                    s = trace_addsym(p[0 .. strlen(p)]);
+                    trace_sympair_add(psp,s,count);
+                    break;
+                default:
+                    if (!isalpha(*buf))
+                    {
+                        if (!sfanin)
+                            psp = &sfanin;
+                        continue;       // regard unrecognized line as separator
+                    }
+                case '?':
+                case '_':
+                case '$':
+                case '@':
+                    p = buf;
+                    while (isgraph(*p))
+                        p++;
+                    *p = 0;
+                    //printf("trace_addsym('%s')\n",buf);
+                    s = trace_addsym(buf[0 .. strlen(buf)]);
+                    if (s.Sfanin)
+                    {   SymPair *sp;
+
+                        for (; sfanin; sfanin = sp)
+                        {
+                            trace_sympair_add(&s.Sfanin,sfanin.sym,sfanin.count);
+                            sp = sfanin.next;
+                            trace_free(sfanin);
+                        }
+                    }
+                    else
+                    {   s.Sfanin = sfanin;
+                    }
+                    sfanin = null;
+                    psp = &s.Sfanout;
+
+                    {   timer_t t;
+
+                        p++;
+                        count = strtoul(p,&p,10);
+                        t = cast(long)strtoull(p,&p,10);
+                        s.totaltime += t;
+                        t = cast(long)strtoull(p,&p,10);
+                        s.functime += t;
+                    }
+                    break;
+            }
+        }
+    L1:
+        fclose(fp);
+    }
+}
+
+////////////////////////// COMPILER INTERFACE /////////////////////
+
+/////////////////////////////////////////////
+// Function called by trace code in function prolog.
+
+void _trace_pro_n()
+{
+    /* Length of string is either:
+     *  db      length
+     *  ascii   string
+     * or:
+     *  db      0x0FF
+     *  db      0
+     *  dw      length
+     *  ascii   string
+     */
+
+  version (OSX)
+  { // 16 byte align stack
+    asm
+    {   naked                           ;
+        pushad                          ;
+        mov     ECX,8*4[ESP]            ;
+        xor     EAX,EAX                 ;
+        mov     AL,[ECX]                ;
+        cmp     AL,0xFF                 ;
+        jne     L1                      ;
+        cmp     byte ptr 1[ECX],0       ;
+        jne     L1                      ;
+        mov     AX,2[ECX]               ;
+        add     8*4[ESP],3              ;
+        add     ECX,3                   ;
+    L1: inc     EAX                     ;
+        inc     ECX                     ;
+        add     8*4[ESP],EAX            ;
+        dec     EAX                     ;
+        sub     ESP,4                   ;
+        push    ECX                     ;
+        push    EAX                     ;
+        call    trace_pro               ;
+        add     ESP,12                  ;
+        popad                           ;
+        ret                             ;
+    }
+  }
+  else
+  {
+    asm
+    {   naked                           ;
+        pushad                          ;
+        mov     ECX,8*4[ESP]            ;
+        xor     EAX,EAX                 ;
+        mov     AL,[ECX]                ;
+        cmp     AL,0xFF                 ;
+        jne     L1                      ;
+        cmp     byte ptr 1[ECX],0       ;
+        jne     L1                      ;
+        mov     AX,2[ECX]               ;
+        add     8*4[ESP],3              ;
+        add     ECX,3                   ;
+    L1: inc     EAX                     ;
+        inc     ECX                     ;
+        add     8*4[ESP],EAX            ;
+        dec     EAX                     ;
+        push    ECX                     ;
+        push    EAX                     ;
+        call    trace_pro               ;
+        add     ESP,8                   ;
+        popad                           ;
+        ret                             ;
+    }
+  }
+}
+
+/////////////////////////////////////////////
+// Function called by trace code in function epilog.
+
+
+void _trace_epi_n()
+{
+  version (OSX)
+  { // 16 byte align stack
+    asm
+    {   naked   ;
+        pushad  ;
+        sub     ESP,12  ;
+    }
+    trace_epi();
+    asm
+    {
+        add     ESP,12  ;
+        popad   ;
+        ret     ;
+    }
+  }
+  else
+  {
+    asm
+    {   naked   ;
+        pushad  ;
+    }
+    trace_epi();
+    asm
+    {
+        popad   ;
+        ret     ;
+    }
+  }
+}
+
+
+version (Windows)
+{
+    extern (Windows)
+    {
+        export int QueryPerformanceCounter(timer_t *);
+        export int QueryPerformanceFrequency(timer_t *);
+    }
+}
+else version (X86)
+{
+    extern (D)
+    {
+        void QueryPerformanceCounter(timer_t* ctr)
+        {
+            asm
+            {   naked                   ;
+                mov       ECX,EAX       ;
+                rdtsc                   ;
+                mov   [ECX],EAX         ;
+                mov   4[ECX],EDX        ;
+                ret                     ;
+            }
+        }
+
+        void QueryPerformanceFrequency(timer_t* freq)
+        {
+            *freq = 3579545;
+        }
+    }
+}
+else
+{
+    static assert(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_AC.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,107 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_AC;
+
+// Object[]
+
+class TypeInfo_AC : TypeInfo
+{
+    override hash_t getHash(in void* p)
+    {   Object[] s = *cast(Object[]*)p;
+        hash_t hash = 0;
+
+        foreach (Object o; s)
+        {
+            if (o)
+                hash += o.toHash();
+        }
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        Object[] s1 = *cast(Object[]*)p1;
+        Object[] s2 = *cast(Object[]*)p2;
+
+        if (s1.length == s2.length)
+        {
+            for (size_t u = 0; u < s1.length; u++)
+            {   Object o1 = s1[u];
+                Object o2 = s2[u];
+
+                // Do not pass null's to Object.opEquals()
+                if (o1 is o2 ||
+                    (!(o1 is null) && !(o2 is null) && o1.opEquals(o2)))
+                    continue;
+                return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        Object[] s1 = *cast(Object[]*)p1;
+        Object[] s2 = *cast(Object[]*)p2;
+        ptrdiff_t c;
+
+        c = cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length;
+        if (c == 0)
+        {
+            for (size_t u = 0; u < s1.length; u++)
+            {   Object o1 = s1[u];
+                Object o2 = s2[u];
+
+                if (o1 is o2)
+                    continue;
+
+                // Regard null references as always being "less than"
+                if (o1)
+                {
+                    if (!o2)
+                    {   c = 1;
+                        break;
+                    }
+                    c = o1.opCmp(o2);
+                    if (c)
+                        break;
+                }
+                else
+                {   c = -1;
+                    break;
+                }
+            }
+        }
+        if (c < 0)
+            c = -1;
+        else if (c > 0)
+            c = 1;
+        return c;
+    }
+
+    override size_t tsize()
+    {
+        return (Object[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(Object);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_Acdouble.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,94 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Acdouble;
+
+private import rt.typeinfo.ti_cdouble;
+
+// cdouble[]
+
+class TypeInfo_Ar : TypeInfo
+{
+    override string toString() { return "cdouble[]"; }
+
+    override hash_t getHash(in void* p)
+    {   cdouble[] s = *cast(cdouble[]*)p;
+        size_t len = s.length;
+        cdouble *str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += (cast(uint *)str)[0];
+            hash += (cast(uint *)str)[1];
+            hash += (cast(uint *)str)[2];
+            hash += (cast(uint *)str)[3];
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        cdouble[] s1 = *cast(cdouble[]*)p1;
+        cdouble[] s2 = *cast(cdouble[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return false;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_r._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        cdouble[] s1 = *cast(cdouble[]*)p1;
+        cdouble[] s2 = *cast(cdouble[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_r._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (cdouble[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(cdouble);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_Acfloat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,92 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Acfloat;
+
+private import rt.typeinfo.ti_cfloat;
+
+// cfloat[]
+
+class TypeInfo_Aq : TypeInfo
+{
+    override string toString() { return "cfloat[]"; }
+
+    override hash_t getHash(in void* p)
+    {   cfloat[] s = *cast(cfloat[]*)p;
+        size_t len = s.length;
+        cfloat *str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += (cast(uint *)str)[0];
+            hash += (cast(uint *)str)[1];
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        cfloat[] s1 = *cast(cfloat[]*)p1;
+        cfloat[] s2 = *cast(cfloat[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return false;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_q._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        cfloat[] s1 = *cast(cfloat[]*)p1;
+        cfloat[] s2 = *cast(cfloat[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_q._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (cfloat[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(cfloat);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_Acreal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,95 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Acreal;
+
+private import rt.typeinfo.ti_creal;
+
+// creal[]
+
+class TypeInfo_Ac : TypeInfo
+{
+    override string toString() { return "creal[]"; }
+
+    override hash_t getHash(in void* p)
+    {   creal[] s = *cast(creal[]*)p;
+        size_t len = s.length;
+        creal *str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += (cast(uint *)str)[0];
+            hash += (cast(uint *)str)[1];
+            hash += (cast(uint *)str)[2];
+            hash += (cast(uint *)str)[3];
+            hash += (cast(uint *)str)[4];
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        creal[] s1 = *cast(creal[]*)p1;
+        creal[] s2 = *cast(creal[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return 0;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_c._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        creal[] s1 = *cast(creal[]*)p1;
+        creal[] s2 = *cast(creal[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_c._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (creal[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(creal);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_Adouble.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,104 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Adouble;
+
+private import rt.typeinfo.ti_double;
+
+// double[]
+
+class TypeInfo_Ad : TypeInfo
+{
+    override string toString() { return "double[]"; }
+
+    override hash_t getHash(in void* p)
+    {   double[] s = *cast(double[]*)p;
+        size_t len = s.length;
+        auto str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += (cast(uint *)str)[0];
+            hash += (cast(uint *)str)[1];
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        double[] s1 = *cast(double[]*)p1;
+        double[] s2 = *cast(double[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return 0;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_d._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        double[] s1 = *cast(double[]*)p1;
+        double[] s2 = *cast(double[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_d._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (double[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(double);
+    }
+}
+
+// idouble[]
+
+class TypeInfo_Ap : TypeInfo_Ad
+{
+    override string toString() { return "idouble[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(idouble);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_Afloat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,103 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Afloat;
+
+private import rt.typeinfo.ti_float;
+
+// float[]
+
+class TypeInfo_Af : TypeInfo
+{
+    override string toString() { return "float[]"; }
+
+    override hash_t getHash(in void* p)
+    {   float[] s = *cast(float[]*)p;
+        size_t len = s.length;
+        auto str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += *cast(uint *)str;
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        float[] s1 = *cast(float[]*)p1;
+        float[] s2 = *cast(float[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return 0;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_f._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        float[] s1 = *cast(float[]*)p1;
+        float[] s2 = *cast(float[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_f._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (float[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(float);
+    }
+}
+
+// ifloat[]
+
+class TypeInfo_Ao : TypeInfo_Af
+{
+    override string toString() { return "ifloat[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(ifloat);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_Ag.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,228 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Ag;
+
+private import rt.util.string;
+private import core.stdc.string;
+
+// byte[]
+
+class TypeInfo_Ag : TypeInfo
+{
+    override string toString() { return "byte[]"; }
+
+    override hash_t getHash(in void* p)
+    {   byte[] s = *cast(byte[]*)p;
+        size_t len = s.length;
+        byte *str = s.ptr;
+        hash_t hash = 0;
+
+        while (1)
+        {
+            switch (len)
+            {
+                case 0:
+                    return hash;
+
+                case 1:
+                    hash *= 9;
+                    hash += *cast(ubyte *)str;
+                    return hash;
+
+                case 2:
+                    hash *= 9;
+                    hash += *cast(ushort *)str;
+                    return hash;
+
+                case 3:
+                    hash *= 9;
+                    hash += (*cast(ushort *)str << 8) +
+                            (cast(ubyte *)str)[2];
+                    return hash;
+
+                default:
+                    hash *= 9;
+                    hash += *cast(uint *)str;
+                    str += 4;
+                    len -= 4;
+                    break;
+            }
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        byte[] s1 = *cast(byte[]*)p1;
+        byte[] s2 = *cast(byte[]*)p2;
+
+        return s1.length == s2.length &&
+               memcmp(cast(byte *)s1, cast(byte *)s2, s1.length) == 0;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        byte[] s1 = *cast(byte[]*)p1;
+        byte[] s2 = *cast(byte[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = s1[u] - s2[u];
+            if (result)
+                return result;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (byte[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(byte);
+    }
+}
+
+
+// ubyte[]
+
+class TypeInfo_Ah : TypeInfo_Ag
+{
+    override string toString() { return "ubyte[]"; }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        char[] s1 = *cast(char[]*)p1;
+        char[] s2 = *cast(char[]*)p2;
+
+        return dstrcmp(s1, s2);
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(ubyte);
+    }
+}
+
+// void[]
+
+class TypeInfo_Av : TypeInfo_Ah
+{
+    override string toString() { return "void[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(void);
+    }
+}
+
+// bool[]
+
+class TypeInfo_Ab : TypeInfo_Ah
+{
+    override string toString() { return "bool[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(bool);
+    }
+}
+
+// char[]
+
+class TypeInfo_Aa : TypeInfo_Ag
+{
+    override string toString() { return "char[]"; }
+
+    override hash_t getHash(in void* p)
+    {   char[] s = *cast(char[]*)p;
+        hash_t hash = 0;
+
+version (all)
+{
+        foreach (char c; s)
+            hash = hash * 11 + c;
+}
+else
+{
+        size_t len = s.length;
+        char *str = s;
+
+        while (1)
+        {
+            switch (len)
+            {
+                case 0:
+                    return hash;
+
+                case 1:
+                    hash *= 9;
+                    hash += *cast(ubyte *)str;
+                    return hash;
+
+                case 2:
+                    hash *= 9;
+                    hash += *cast(ushort *)str;
+                    return hash;
+
+                case 3:
+                    hash *= 9;
+                    hash += (*cast(ushort *)str << 8) +
+                            (cast(ubyte *)str)[2];
+                    return hash;
+
+                default:
+                    hash *= 9;
+                    hash += *cast(uint *)str;
+                    str += 4;
+                    len -= 4;
+                    break;
+            }
+        }
+}
+        return hash;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(char);
+    }
+}
+
+// string
+
+class TypeInfo_Aya : TypeInfo_Aa
+{
+    override string toString() { return "immutable(char)[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(immutable(char));
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_Aint.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,140 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Aint;
+
+private import core.stdc.string;
+
+// int[]
+
+class TypeInfo_Ai : TypeInfo
+{
+    override string toString() { return "int[]"; }
+
+    override hash_t getHash(in void* p)
+    {   int[] s = *cast(int[]*)p;
+        auto len = s.length;
+        auto str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += *cast(uint *)str;
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        int[] s1 = *cast(int[]*)p1;
+        int[] s2 = *cast(int[]*)p2;
+
+        return s1.length == s2.length &&
+               memcmp(cast(void *)s1, cast(void *)s2, s1.length * int.sizeof) == 0;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        int[] s1 = *cast(int[]*)p1;
+        int[] s2 = *cast(int[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = s1[u] - s2[u];
+            if (result)
+                return result;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (int[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(int);
+    }
+}
+
+unittest
+{
+    int[][] a = [[5,3,8,7], [2,5,3,8,7]];
+    a.sort;
+    assert(a == [[2,5,3,8,7], [5,3,8,7]]);
+
+    a = [[5,3,8,7], [5,3,8]];
+    a.sort;
+    assert(a == [[5,3,8], [5,3,8,7]]);
+}
+
+// uint[]
+
+class TypeInfo_Ak : TypeInfo_Ai
+{
+    override string toString() { return "uint[]"; }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        uint[] s1 = *cast(uint[]*)p1;
+        uint[] s2 = *cast(uint[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = s1[u] - s2[u];
+            if (result)
+                return result;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(uint);
+    }
+}
+
+// dchar[]
+
+class TypeInfo_Aw : TypeInfo_Ak
+{
+    override string toString() { return "dchar[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(dchar);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_Along.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,120 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Along;
+
+private import core.stdc.string;
+
+// long[]
+
+class TypeInfo_Al : TypeInfo
+{
+    override string toString() { return "long[]"; }
+
+    override hash_t getHash(in void* p)
+    {   long[] s = *cast(long[]*)p;
+        size_t len = s.length;
+        auto str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += *cast(uint *)str + *(cast(uint *)str + 1);
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        long[] s1 = *cast(long[]*)p1;
+        long[] s2 = *cast(long[]*)p2;
+
+        return s1.length == s2.length &&
+               memcmp(cast(void *)s1, cast(void *)s2, s1.length * long.sizeof) == 0;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        long[] s1 = *cast(long[]*)p1;
+        long[] s2 = *cast(long[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (s1[u] < s2[u])
+                return -1;
+            else if (s1[u] > s2[u])
+                return 1;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (long[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(long);
+    }
+}
+
+
+// ulong[]
+
+class TypeInfo_Am : TypeInfo_Al
+{
+    override string toString() { return "ulong[]"; }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        ulong[] s1 = *cast(ulong[]*)p1;
+        ulong[] s2 = *cast(ulong[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (s1[u] < s2[u])
+                return -1;
+            else if (s1[u] > s2[u])
+                return 1;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(ulong);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_Areal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,105 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Areal;
+
+private import rt.typeinfo.ti_real;
+
+// real[]
+
+class TypeInfo_Ae : TypeInfo
+{
+    override string toString() { return "real[]"; }
+
+    override hash_t getHash(in void* p)
+    {   real[] s = *cast(real[]*)p;
+        size_t len = s.length;
+        auto str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += (cast(uint *)str)[0];
+            hash += (cast(uint *)str)[1];
+            hash += (cast(ushort *)str)[4];
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        real[] s1 = *cast(real[]*)p1;
+        real[] s2 = *cast(real[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return false;
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!TypeInfo_e._equals(s1[u], s2[u]))
+                return false;
+        }
+        return true;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        real[] s1 = *cast(real[]*)p1;
+        real[] s2 = *cast(real[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_e._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (real[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(real);
+    }
+}
+
+// ireal[]
+
+class TypeInfo_Aj : TypeInfo_Ae
+{
+    override string toString() { return "ireal[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(ireal);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_Ashort.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,143 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_Ashort;
+
+private import core.stdc.string;
+
+// short[]
+
+class TypeInfo_As : TypeInfo
+{
+    override string toString() { return "short[]"; }
+
+    override hash_t getHash(in void* p)
+    {   short[] s = *cast(short[]*)p;
+        size_t len = s.length;
+        short *str = s.ptr;
+        hash_t hash = 0;
+
+        while (1)
+        {
+            switch (len)
+            {
+                case 0:
+                    return hash;
+
+                case 1:
+                    hash *= 9;
+                    hash += *cast(ushort *)str;
+                    return hash;
+
+                default:
+                    hash *= 9;
+                    hash += *cast(uint *)str;
+                    str += 2;
+                    len -= 2;
+                    break;
+            }
+        }
+
+        return hash;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        short[] s1 = *cast(short[]*)p1;
+        short[] s2 = *cast(short[]*)p2;
+
+        return s1.length == s2.length &&
+               memcmp(cast(void *)s1, cast(void *)s2, s1.length * short.sizeof) == 0;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        short[] s1 = *cast(short[]*)p1;
+        short[] s2 = *cast(short[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = s1[u] - s2[u];
+            if (result)
+                return result;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (short[]).sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(short);
+    }
+}
+
+
+// ushort[]
+
+class TypeInfo_At : TypeInfo_As
+{
+    override string toString() { return "ushort[]"; }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        ushort[] s1 = *cast(ushort[]*)p1;
+        ushort[] s2 = *cast(ushort[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = s1[u] - s2[u];
+            if (result)
+                return result;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    override TypeInfo next()
+    {
+        return typeid(ushort);
+    }
+}
+
+// wchar[]
+
+class TypeInfo_Au : TypeInfo_At
+{
+    override string toString() { return "wchar[]"; }
+
+    override TypeInfo next()
+    {
+        return typeid(wchar);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_C.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,63 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_C;
+
+// Object
+
+class TypeInfo_C : TypeInfo
+{
+    override hash_t getHash(in void* p)
+    {
+        Object o = *cast(Object*)p;
+        return o ? o.toHash() : 0;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        Object o1 = *cast(Object*)p1;
+        Object o2 = *cast(Object*)p2;
+
+        return o1 == o2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        Object o1 = *cast(Object*)p1;
+        Object o2 = *cast(Object*)p2;
+        int c = 0;
+
+        // Regard null references as always being "less than"
+        if (!(o1 is o2))
+        {
+            if (o1)
+            {   if (!o2)
+                    c = 1;
+                else
+                    c = o1.opCmp(o2);
+            }
+            else
+                c = -1;
+        }
+        return c;
+    }
+
+    override size_t tsize()
+    {
+        return Object.sizeof;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_byte.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,49 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_byte;
+
+// byte
+
+class TypeInfo_g : TypeInfo
+{
+    override string toString() { return "byte"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(byte *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(byte *)p1 == *cast(byte *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(byte *)p1 - *cast(byte *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return byte.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        byte t;
+
+        t = *cast(byte *)p1;
+        *cast(byte *)p1 = *cast(byte *)p2;
+        *cast(byte *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_cdouble.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,77 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_cdouble;
+
+// cdouble
+
+class TypeInfo_r : TypeInfo
+{
+    override string toString() { return "cdouble"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
+               (cast(uint *)p)[2] + (cast(uint *)p)[3];
+    }
+
+    static equals_t _equals(cdouble f1, cdouble f2)
+    {
+        return f1 == f2;
+    }
+
+    static int _compare(cdouble f1, cdouble f2)
+    {   int result;
+
+        if (f1.re < f2.re)
+            result = -1;
+        else if (f1.re > f2.re)
+            result = 1;
+        else if (f1.im < f2.im)
+            result = -1;
+        else if (f1.im > f2.im)
+            result = 1;
+        else
+            result = 0;
+        return result;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(cdouble *)p1, *cast(cdouble *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(cdouble *)p1, *cast(cdouble *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return cdouble.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        cdouble t;
+
+        t = *cast(cdouble *)p1;
+        *cast(cdouble *)p1 = *cast(cdouble *)p2;
+        *cast(cdouble *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable cdouble r;
+
+        return (cast(cdouble *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_cfloat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,76 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_cfloat;
+
+// cfloat
+
+class TypeInfo_q : TypeInfo
+{
+    override string toString() { return "cfloat"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return (cast(uint *)p)[0] + (cast(uint *)p)[1];
+    }
+
+    static equals_t _equals(cfloat f1, cfloat f2)
+    {
+        return f1 == f2;
+    }
+
+    static int _compare(cfloat f1, cfloat f2)
+    {   int result;
+
+        if (f1.re < f2.re)
+            result = -1;
+        else if (f1.re > f2.re)
+            result = 1;
+        else if (f1.im < f2.im)
+            result = -1;
+        else if (f1.im > f2.im)
+            result = 1;
+        else
+            result = 0;
+        return result;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(cfloat *)p1, *cast(cfloat *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(cfloat *)p1, *cast(cfloat *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return cfloat.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        cfloat t;
+
+        t = *cast(cfloat *)p1;
+        *cast(cfloat *)p1 = *cast(cfloat *)p2;
+        *cast(cfloat *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable cfloat r;
+
+        return (cast(cfloat *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_char.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,55 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_char;
+
+// char
+
+class TypeInfo_a : TypeInfo
+{
+    override string toString() { return "char"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(char *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(char *)p1 == *cast(char *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(char *)p1 - *cast(char *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return char.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        char t;
+
+        t = *cast(char *)p1;
+        *cast(char *)p1 = *cast(char *)p2;
+        *cast(char *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable char c;
+
+        return (cast(char *)&c)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_creal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,78 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_creal;
+
+// creal
+
+class TypeInfo_c : TypeInfo
+{
+    override string toString() { return "creal"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
+               (cast(uint *)p)[2] + (cast(uint *)p)[3] +
+               (cast(uint *)p)[4];
+    }
+
+    static equals_t _equals(creal f1, creal f2)
+    {
+        return f1 == f2;
+    }
+
+    static int _compare(creal f1, creal f2)
+    {   int result;
+
+        if (f1.re < f2.re)
+            result = -1;
+        else if (f1.re > f2.re)
+            result = 1;
+        else if (f1.im < f2.im)
+            result = -1;
+        else if (f1.im > f2.im)
+            result = 1;
+        else
+            result = 0;
+        return result;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(creal *)p1, *cast(creal *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(creal *)p1, *cast(creal *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return creal.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        creal t;
+
+        t = *cast(creal *)p1;
+        *cast(creal *)p1 = *cast(creal *)p2;
+        *cast(creal *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable creal r;
+
+        return (cast(creal *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_dchar.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,55 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_dchar;
+
+// dchar
+
+class TypeInfo_w : TypeInfo
+{
+    override string toString() { return "dchar"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(dchar *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(dchar *)p1 == *cast(dchar *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(dchar *)p1 - *cast(dchar *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return dchar.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        dchar t;
+
+        t = *cast(dchar *)p1;
+        *cast(dchar *)p1 = *cast(dchar *)p2;
+        *cast(dchar *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable dchar c;
+
+        return (cast(dchar *)&c)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_delegate.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,50 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_delegate;
+
+// delegate
+
+alias void delegate(int) dg;
+
+class TypeInfo_D : TypeInfo
+{
+    override hash_t getHash(in void* p)
+    {   long l = *cast(long *)p;
+
+        return cast(uint)(l + (l >> 32));
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(dg *)p1 == *cast(dg *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return dg.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        dg t;
+
+        t = *cast(dg *)p1;
+        *cast(dg *)p1 = *cast(dg *)p2;
+        *cast(dg *)p2 = t;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_double.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,75 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_double;
+
+// double
+
+class TypeInfo_d : TypeInfo
+{
+    override string toString() { return "double"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return (cast(uint *)p)[0] + (cast(uint *)p)[1];
+    }
+
+    static equals_t _equals(double f1, double f2)
+    {
+        return f1 == f2 ||
+                (f1 !<>= f1 && f2 !<>= f2);
+    }
+
+    static int _compare(double d1, double d2)
+    {
+        if (d1 !<>= d2)         // if either are NaN
+        {
+            if (d1 !<>= d1)
+            {   if (d2 !<>= d2)
+                    return 0;
+                return -1;
+            }
+            return 1;
+        }
+        return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(double *)p1, *cast(double *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(double *)p1, *cast(double *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return double.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        double t;
+
+        t = *cast(double *)p1;
+        *cast(double *)p1 = *cast(double *)p2;
+        *cast(double *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable double r;
+
+        return (cast(double *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_float.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,75 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_float;
+
+// float
+
+class TypeInfo_f : TypeInfo
+{
+    override string toString() { return "float"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(uint *)p;
+    }
+
+    static equals_t _equals(float f1, float f2)
+    {
+        return f1 == f2 ||
+                (f1 !<>= f1 && f2 !<>= f2);
+    }
+
+    static int _compare(float d1, float d2)
+    {
+        if (d1 !<>= d2)         // if either are NaN
+        {
+            if (d1 !<>= d1)
+            {   if (d2 !<>= d2)
+                    return 0;
+                return -1;
+            }
+            return 1;
+        }
+        return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(float *)p1, *cast(float *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(float *)p1, *cast(float *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return float.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        float t;
+
+        t = *cast(float *)p1;
+        *cast(float *)p1 = *cast(float *)p2;
+        *cast(float *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable float r;
+
+        return (cast(float *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_idouble.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,22 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_idouble;
+
+// idouble
+
+private import rt.typeinfo.ti_double;
+
+class TypeInfo_p : TypeInfo_d
+{
+    override string toString() { return "idouble"; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_ifloat.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,22 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ifloat;
+
+// ifloat
+
+private import rt.typeinfo.ti_float;
+
+class TypeInfo_o : TypeInfo_f
+{
+    override string toString() { return "ifloat"; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_int.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,53 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_int;
+
+// int
+
+class TypeInfo_i : TypeInfo
+{
+    override string toString() { return "int"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(uint *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(uint *)p1 == *cast(uint *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        if (*cast(int*) p1 < *cast(int*) p2)
+            return -1;
+        else if (*cast(int*) p1 > *cast(int*) p2)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return int.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        int t;
+
+        t = *cast(int *)p1;
+        *cast(int *)p1 = *cast(int *)p2;
+        *cast(int *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_ireal.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,22 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ireal;
+
+// ireal
+
+private import rt.typeinfo.ti_real;
+
+class TypeInfo_j : TypeInfo_e
+{
+    override string toString() { return "ireal"; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_long.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,53 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_long;
+
+// long
+
+class TypeInfo_l : TypeInfo
+{
+    override string toString() { return "long"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(uint *)p + (cast(uint *)p)[1];
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(long *)p1 == *cast(long *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        if (*cast(long *)p1 < *cast(long *)p2)
+            return -1;
+        else if (*cast(long *)p1 > *cast(long *)p2)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return long.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        long t;
+
+        t = *cast(long *)p1;
+        *cast(long *)p1 = *cast(long *)p2;
+        *cast(long *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_ptr.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,57 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ptr;
+
+// pointer
+
+class TypeInfo_P : TypeInfo
+{
+    override hash_t getHash(in void* p)
+    {
+        return cast(uint)*cast(void* *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(void* *)p1 == *cast(void* *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        auto c = *cast(void* *)p1 - *cast(void* *)p2;
+        if (c < 0)
+            return -1;
+        else if (c > 0)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return (void*).sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        void* t;
+
+        t = *cast(void* *)p1;
+        *cast(void* *)p1 = *cast(void* *)p2;
+        *cast(void* *)p2 = t;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_real.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,75 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_real;
+
+// real
+
+class TypeInfo_e : TypeInfo
+{
+    override string toString() { return "real"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return (cast(uint *)p)[0] + (cast(uint *)p)[1] + (cast(ushort *)p)[4];
+    }
+
+    static equals_t _equals(real f1, real f2)
+    {
+        return f1 == f2 ||
+                (f1 !<>= f1 && f2 !<>= f2);
+    }
+
+    static int _compare(real d1, real d2)
+    {
+        if (d1 !<>= d2)         // if either are NaN
+        {
+            if (d1 !<>= d1)
+            {   if (d2 !<>= d2)
+                    return 0;
+                return -1;
+            }
+            return 1;
+        }
+        return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return _equals(*cast(real *)p1, *cast(real *)p2);
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return _compare(*cast(real *)p1, *cast(real *)p2);
+    }
+
+    override size_t tsize()
+    {
+        return real.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        real t;
+
+        t = *cast(real *)p1;
+        *cast(real *)p1 = *cast(real *)p2;
+        *cast(real *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable real r;
+
+        return (cast(real *)&r)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_short.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,49 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_short;
+
+// short
+
+class TypeInfo_s : TypeInfo
+{
+    override string toString() { return "short"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(short *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(short *)p1 == *cast(short *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(short *)p1 - *cast(short *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return short.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        short t;
+
+        t = *cast(short *)p1;
+        *cast(short *)p1 = *cast(short *)p2;
+        *cast(short *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_ubyte.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,54 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ubyte;
+
+// ubyte
+
+class TypeInfo_h : TypeInfo
+{
+    override string toString() { return "ubyte"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(ubyte *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(ubyte *)p1 == *cast(ubyte *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(ubyte *)p1 - *cast(ubyte *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return ubyte.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        ubyte t;
+
+        t = *cast(ubyte *)p1;
+        *cast(ubyte *)p1 = *cast(ubyte *)p2;
+        *cast(ubyte *)p2 = t;
+    }
+}
+
+class TypeInfo_b : TypeInfo_h
+{
+    override string toString() { return "bool"; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_uint.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,53 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_uint;
+
+// uint
+
+class TypeInfo_k : TypeInfo
+{
+    override string toString() { return "uint"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(uint *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(uint *)p1 == *cast(uint *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        if (*cast(uint*) p1 < *cast(uint*) p2)
+            return -1;
+        else if (*cast(uint*) p1 > *cast(uint*) p2)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return uint.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        int t;
+
+        t = *cast(uint *)p1;
+        *cast(uint *)p1 = *cast(uint *)p2;
+        *cast(uint *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_ulong.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,53 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ulong;
+
+// ulong
+
+class TypeInfo_m : TypeInfo
+{
+    override string toString() { return "ulong"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(uint *)p + (cast(uint *)p)[1];
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(ulong *)p1 == *cast(ulong *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        if (*cast(ulong *)p1 < *cast(ulong *)p2)
+            return -1;
+        else if (*cast(ulong *)p1 > *cast(ulong *)p2)
+            return 1;
+        return 0;
+    }
+
+    override size_t tsize()
+    {
+        return ulong.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        ulong t;
+
+        t = *cast(ulong *)p1;
+        *cast(ulong *)p1 = *cast(ulong *)p2;
+        *cast(ulong *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_ushort.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,49 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_ushort;
+
+// ushort
+
+class TypeInfo_t : TypeInfo
+{
+    override string toString() { return "ushort"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(ushort *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(ushort *)p1 == *cast(ushort *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(ushort *)p1 - *cast(ushort *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return ushort.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        ushort t;
+
+        t = *cast(ushort *)p1;
+        *cast(ushort *)p1 = *cast(ushort *)p2;
+        *cast(ushort *)p2 = t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_void.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,54 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_void;
+
+// void
+
+class TypeInfo_v : TypeInfo
+{
+    override string toString() { return "void"; }
+
+    override hash_t getHash(in void* p)
+    {
+        assert(0);
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(byte *)p1 == *cast(byte *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(byte *)p1 - *cast(byte *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return void.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        byte t;
+
+        t = *cast(byte *)p1;
+        *cast(byte *)p1 = *cast(byte *)p2;
+        *cast(byte *)p2 = t;
+    }
+
+    override uint flags()
+    {
+        return 1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/typeinfo/ti_wchar.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,55 @@
+/**
+ * TypeInfo support code.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.typeinfo.ti_wchar;
+
+// wchar
+
+class TypeInfo_u : TypeInfo
+{
+    override string toString() { return "wchar"; }
+
+    override hash_t getHash(in void* p)
+    {
+        return *cast(wchar *)p;
+    }
+
+    override equals_t equals(in void* p1, in void* p2)
+    {
+        return *cast(wchar *)p1 == *cast(wchar *)p2;
+    }
+
+    override int compare(in void* p1, in void* p2)
+    {
+        return *cast(wchar *)p1 - *cast(wchar *)p2;
+    }
+
+    override size_t tsize()
+    {
+        return wchar.sizeof;
+    }
+
+    override void swap(void *p1, void *p2)
+    {
+        wchar t;
+
+        t = *cast(wchar *)p1;
+        *cast(wchar *)p1 = *cast(wchar *)p2;
+        *cast(wchar *)p2 = t;
+    }
+
+    override void[] init()
+    {   static immutable wchar c;
+
+        return (cast(wchar *)&c)[0 .. 1];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/util/console.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,54 @@
+/**
+ * The console module contains some simple routines for console output.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.util.console;
+
+
+private
+{
+    version (Windows)
+    {
+        import core.sys.windows.windows;
+    }
+    else version( Posix )
+    {
+        import core.sys.posix.unistd;
+    }
+    import rt.util.string;
+}
+
+
+struct Console
+{
+    Console opCall( in char[] val )
+    {
+        version( Windows )
+        {
+            uint count = void;
+            WriteFile( GetStdHandle( 0xfffffff5 ), val.ptr, val.length, &count, null );
+        }
+        else version( Posix )
+        {
+            write( 2, val.ptr, val.length );
+        }
+        return this;
+    }
+
+
+    Console opCall( uint val )
+    {
+            char[10] tmp = void;
+            return opCall( tmp.intToString( val ) );
+    }
+}
+
+__gshared Console console;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/util/cpuid.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,719 @@
+/** 
+ * Identify the characteristics of the host CPU, providing information
+ * about cache sizes and assembly optimisation hints.
+ *
+ * Some of this information was extremely difficult to track down. Some of the
+ * documents below were found only in cached versions stored by search engines!
+ * This code relies on information found in:
+	
+ * - "Intel(R) 64 and IA-32 Architectures Software Developers Manual,
+ *	  Volume 2A: Instruction Set Reference, A-M" (2007).
+ * - "AMD CPUID Specification", Advanced Micro Devices, Rev 2.28 (2008).
+ * - "AMD Processor Recognition Application Note For Processors Prior to AMD
+ *    Family 0Fh Processors", Advanced Micro Devices, Rev 3.13 (2005).
+ * - "AMD Geode(TM) GX Processors Data Book",
+ *    Advanced Micro Devices, Publication ID 31505E, (2005).
+ * - "AMD K6 Processor Code Optimisation", Advanced Micro Devices, Rev D (2000).
+ * - "Application note 106: Software Customization for the 6x86 Family",
+ *    Cyrix Corporation, Rev 1.5 (1998)
+ * - http://ftp.intron.ac/pub/document/cpu/cpuid.htm
+ * - "Geode(TM) GX1 Processor Series Low Power Integrated X86 Solution",
+ *   National Semiconductor, (2002)
+ * - "The VIA Isaiah Architecture", G. Glenn Henry, Centaur Technology, Inc (2008).
+ * - http://www.sandpile.org/ia32/cpuid.htm
+ * - http://grafi.ii.pw.edu.pl/gbm/x86/cpuid.html
+ * - "What every programmer should know about memory",
+ *    Ulrich Depper, Red Hat, Inc., (2007). 
+ * 
+ * Bugs: Currently only works on x86 and Itanium CPUs.
+ *      Many processors have bugs in their microcode for the CPUID instruction,
+ *      so sometimes the cache information may be incorrect.
+ *
+ * Copyright: Copyright Don Clugston 2007 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Don Clugston, Tomas Lindquist Olsen &lt;tomas@famolsen.dk&gt;
+ *
+ *          Copyright Don Clugston 2007 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.util.cpuid;
+
+// If optimizing for a particular processor, it is generally better
+// to identify based on features rather than model. NOTE: Normally
+// it's only worthwhile to optimise for the latest Intel and AMD CPU,
+// with a backup for other CPUs.
+// Pentium    -- preferPentium1()
+// PMMX       --   + mmx()
+// PPro       -- default
+// PII        --   + mmx()
+// PIII       --   + mmx() + sse()
+// PentiumM   --   + mmx() + sse() + sse2()
+// Pentium4   -- preferPentium4()
+// PentiumD   --   + isX86_64()
+// Core2      -- default + isX86_64()
+// AMD K5     -- preferPentium1()
+// AMD K6     --   + mmx()
+// AMD K6-II  --   + mmx() + 3dnow()
+// AMD K7     -- preferAthlon()
+// AMD K8     --   + sse2()
+// AMD K10    --   + isX86_64()
+// Cyrix 6x86 -- preferPentium1()
+//    6x86MX  --   + mmx()
+
+public:
+
+/// Cache size and behaviour
+struct CacheInfo
+{
+    /// Size of the cache, in kilobytes, per CPU.
+    /// For L1 unified (data + code) caches, this size is half the physical size.
+    /// (we don't halve it for larger sizes, since normally
+    /// data size is much greater than code size for critical loops).
+	uint size;
+    /// Number of ways of associativity, eg:
+    /// 1 = direct mapped
+    /// 2 = 2-way set associative
+    /// 3 = 3-way set associative
+    /// ubyte.max = fully associative
+	ubyte associativity;
+    /// Number of bytes read into the cache when a cache miss occurs.
+	uint lineSize;
+}
+
+public:
+	/// Returns vendor string, for display purposes only.
+	/// Do NOT use this to determine features!
+	/// Note that some CPUs have programmable vendorIDs.
+	char[] vendor()		{return vendorID;}
+	/// Returns processor string, for display purposes only
+	char[] processor()	{return processorName;}    
+	
+	/// The data caches. If there are fewer than 5 physical caches levels,
+	/// the remaining levels are set to uint.max (== entire memory space)
+	__gshared CacheInfo[5] datacache;
+	/// Does it have an x87 FPU on-chip?
+	bool x87onChip()    {return (features&FPU_BIT)!=0;}
+    /// Is MMX supported?
+    bool mmx()			{return (features&MMX_BIT)!=0;}
+    /// Is SSE supported?
+    bool sse()			{return (features&SSE_BIT)!=0;}
+    /// Is SSE2 supported?
+    bool sse2()			{return (features&SSE2_BIT)!=0;}
+    /// Is SSE3 supported?
+    bool sse3()			{return (miscfeatures&SSE3_BIT)!=0;}
+    /// Is SSSE3 supported?
+    bool ssse3()		{return (miscfeatures&SSSE3_BIT)!=0;}
+    /// Is SSE4.1 supported?
+    bool sse41()		{return (miscfeatures&SSE41_BIT)!=0;}
+    /// Is SSE4.2 supported?
+    bool sse42()		{return (miscfeatures&SSE42_BIT)!=0;}
+    /// Is SSE4a supported?
+    bool sse4a()        {return (amdmiscfeatures&SSE4A_BIT)!=0;}
+    /// Is SSE5 supported?
+    bool sse5()			{return (amdmiscfeatures&SSE5_BIT)!=0;}
+    /// Is AMD 3DNOW supported?
+    bool amd3dnow()		{return (amdfeatures&AMD_3DNOW_BIT)!=0;}
+    /// Is AMD 3DNOW Ext supported?
+    bool amd3dnowExt()	{return (amdfeatures&AMD_3DNOW_EXT_BIT)!=0;}
+    /// Are AMD extensions to MMX supported?
+    bool amdMmx()		{return (amdfeatures&AMD_MMX_BIT)!=0;}
+    /// Is fxsave/fxrstor supported?
+    bool hasFxsr()			{return (features&FXSR_BIT)!=0;}
+    /// Is cmov supported?
+    bool hasCmov()			{return (features&CMOV_BIT)!=0;}
+    /// Is rdtsc supported?
+    bool hasRdtsc()			{return (features&TIMESTAMP_BIT)!=0;}
+    /// Is cmpxchg8b supported?
+    bool hasCmpxchg8b()		{return (features&CMPXCHG8B_BIT)!=0;}
+    /// Is cmpxchg8b supported?
+    bool hasCmpxchg16b()	{return (miscfeatures&CMPXCHG16B_BIT)!=0;}
+    /// Is 3DNow prefetch supported?
+    bool has3dnowPrefetch()
+    	{return (amdmiscfeatures&AMD_3DNOW_PREFETCH_BIT)!=0;}
+    /// Are LAHF and SAHF supported in 64-bit mode?
+    bool hasLahfSahf()			{return (amdmiscfeatures&LAHFSAHF_BIT)!=0;}
+    /// Is POPCNT supported?
+    bool hasPopcnt()		{return (miscfeatures&POPCNT_BIT)!=0;}    
+    /// Is LZCNT supported?
+    bool hasLzcnt()			{return (amdmiscfeatures&LZCNT_BIT)!=0;}
+    /// Is this an Intel64 or AMD 64?
+    bool isX86_64()			{return (amdfeatures&AMD64_BIT)!=0;}
+            
+    /// Is this an IA64 (Itanium) processor?
+    bool isItanium()        { return (features&IA64_BIT)!=0; }
+
+    /// Is hyperthreading supported?
+    bool hyperThreading()   { return maxThreads>maxCores; }
+    /// Returns number of threads per CPU
+    uint threadsPerCPU()	{return maxThreads;}
+    /// Returns number of cores in CPU
+    uint coresPerCPU()		{return maxCores;}
+    
+    /// Optimisation hints for assembly code.
+    /// For forward compatibility, the CPU is compared against different
+    /// microarchitectures. For 32-bit X86, comparisons are made against
+    /// the Intel PPro/PII/PIII/PM family.
+    ///
+    /// The major 32-bit x86 microarchitecture 'dynasties' have been:
+    /// (1) Intel P6 (PentiumPro, PII, PIII, PM, Core, Core2).
+    /// (2) AMD Athlon (K7, K8, K10).
+    /// (3) Intel NetBurst (Pentium 4, Pentium D).
+    /// (4) In-order Pentium (Pentium1, PMMX)
+    /// Other early CPUs (Nx586, AMD K5, K6, Centaur C3, Transmeta,
+    ///   Cyrix, Rise) were mostly in-order.
+    /// Some new processors do not fit into the existing categories:
+    /// Intel Atom 230/330 (family 6, model 0x1C) is an in-order core.
+    /// Centaur Isiah = VIA Nano (family 6, model F) is an out-of-order core.
+    ///
+    /// Within each dynasty, the optimisation techniques are largely
+    /// identical (eg, use instruction pairing for group 4). Major
+    /// instruction set improvements occur within each group.
+    
+    /// Does this CPU perform better on AMD K7 code than PentiumPro..Core2 code?
+    bool preferAthlon() { return probablyAMD && family >=6; }
+    /// Does this CPU perform better on Pentium4 code than PentiumPro..Core2 code?
+    bool preferPentium4() { return probablyIntel && family == 0xF; }
+    /// Does this CPU perform better on Pentium I code than Pentium Pro code?
+    bool preferPentium1() { return family < 6 || (family==6 && model < 0xF && !probablyIntel); }
+
+__gshared:
+public:
+    /// Processor type (vendor-dependent).
+    /// This should be visible ONLY for display purposes.
+    uint stepping, model, family;
+    uint numCacheLevels = 1;
+private:
+	bool probablyIntel; // true = _probably_ an Intel processor, might be faking
+	bool probablyAMD; // true = _probably_ an AMD processor
+	char [12] vendorID;
+	char [] processorName;
+	char [48] processorNameBuffer;
+	uint features = 0;     // mmx, sse, sse2, hyperthreading, etc
+	uint miscfeatures = 0; // sse3, etc.
+	uint amdfeatures = 0;  // 3DNow!, mmxext, etc
+	uint amdmiscfeatures = 0; // sse4a, sse5, svm, etc
+	uint maxCores = 1;
+	uint maxThreads = 1;
+	// Note that this may indicate multi-core rather than hyperthreading.
+    bool hyperThreadingBit()	{ return (features&HTT_BIT)!=0;}
+    
+    // feature flags CPUID1_EDX
+    enum : uint
+    {
+    	FPU_BIT = 1,
+	    TIMESTAMP_BIT = 1<<4, // rdtsc
+	    MDSR_BIT = 1<<5,      // RDMSR/WRMSR
+	    CMPXCHG8B_BIT = 1<<8,
+    	    CMOV_BIT = 1<<15,
+	    MMX_BIT = 1<<23,
+	    FXSR_BIT = 1<<24,
+	    SSE_BIT = 1<<25,
+	    SSE2_BIT = 1<<26,
+	    HTT_BIT = 1<<28,
+	    IA64_BIT = 1<<30
+    }
+    // feature flags misc CPUID1_ECX
+    enum : uint
+    {
+	    SSE3_BIT = 1,
+            PCLMULQDQ_BIT = 1<<1, // from AVX
+	    MWAIT_BIT = 1<<3,
+	    SSSE3_BIT = 1<<9,
+            FMA_BIT = 1<<12,     // from AVX
+	    CMPXCHG16B_BIT = 1<<13,
+	    SSE41_BIT = 1<<19,
+	    SSE42_BIT = 1<<20,
+	    POPCNT_BIT = 1<<23,
+            AES_BIT = 1<<25, // AES instructions from AVX
+            OSXSAVE_BIT = 1<<27, // Used for AVX
+            AVX_BIT = 1<<28
+    }
+/+    
+version(X86_64) {    
+    bool hasAVXinHardware() {
+        // This only indicates hardware support, not OS support.
+        return (miscfeatures&AVX_BIT) && (miscfeatures&OSXSAVE_BIT);
+    }
+    // Is AVX supported (in both hardware & OS)?
+    bool Avx() {
+        if (!hasAVXinHardware()) return false;
+        // Check for OS support
+        uint xfeatures;
+        asm {mov ECX, 0; xgetbv; mov xfeatures, EAX; }
+        return (xfeatures&0x6)==6;
+    }
+    bool hasAvxFma() {
+        if (!AVX()) return false;
+        return (features&FMA_BIT)!=0;        
+    }
+}
++/    
+    // AMD feature flags CPUID80000001_EDX
+    enum : uint
+    {
+	    AMD_MMX_BIT = 1<<22,
+//	    FXR_OR_CYRIXMMX_BIT = 1<<24, // Cyrix/NS: 6x86MMX instructions. 
+	    FFXSR_BIT = 1<<25,
+	    PAGE1GB_BIT = 1<<26, // support for 1GB pages
+	    RDTSCP_BIT = 1<<27,
+	    AMD64_BIT = 1<<29,
+	    AMD_3DNOW_EXT_BIT = 1<<30,
+	    AMD_3DNOW_BIT = 1<<31
+    }
+    // AMD misc feature flags CPUID80000001_ECX
+    enum : uint
+    {
+    	LAHFSAHF_BIT = 1,
+    	LZCNT_BIT = 1<<5,
+    	SSE4A_BIT = 1<<6,    	
+    	AMD_3DNOW_PREFETCH_BIT = 1<<8,
+    	SSE5_BIT = 1<<11
+    }
+
+version(GNU){
+    // GDC is a filthy liar. It can't actually do inline asm.
+} else version(D_InlineAsm_X86) {
+    version = Really_D_InlineAsm_X86;
+}
+
+version(Really_D_InlineAsm_X86) {
+// Note that this code will also work for Itanium in x86 mode.
+
+shared uint max_cpuid, max_extended_cpuid;
+
+// CPUID2: "cache and tlb information"
+void getcacheinfoCPUID2()
+{
+	// We are only interested in the data caches
+	void decipherCpuid2(ubyte x) {
+		if (x==0) return;
+		// Values from http://www.sandpile.org/ia32/cpuid.htm.
+		// Includes Itanium and non-Intel CPUs.
+		//
+		immutable ubyte [47] ids = [
+			0x0A, 0x0C, 0x2C, 0x60, 0x0E, 0x66, 0x67, 0x68,
+			// level 2 cache
+			0x41, 0x42, 0x43, 0x44, 0x45, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7F,
+		    0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x49, 0x4E,
+		    0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x48, 0x80, 0x81,
+		    // level 3 cache
+			0x22, 0x23, 0x25, 0x29, 0x46, 0x47, 0x4A, 0x4B, 0x4C, 0x4D
+		];
+		immutable uint [47] sizes = [
+			8, 16, 32, 16, 24, 8, 16, 32,
+		    128, 256, 512, 1024, 2048, 1024, 128, 256, 512, 1024, 2048, 512,
+		    256, 512, 1024, 2048, 512, 1024, 4096, 6*1024,
+		    128, 192, 128, 256, 384, 512, 3072, 512, 128,		    
+			512, 1024, 2048, 4096, 4096, 8192, 6*1024, 8192, 12*1024, 16*1024
+		];
+	// CPUBUG: Pentium M reports 0x2C but tests show it is only 4-way associative
+		immutable ubyte [47] ways = [
+			2, 4, 8, 8, 6, 4, 4, 4,
+		    4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 2,
+		    8, 8, 8, 8, 4, 8, 16, 24,
+		    4, 6, 2, 4, 6, 4, 12, 8, 8,
+			4, 8, 8, 8, 4, 8, 12, 16, 12, 16
+		];
+		enum { FIRSTDATA2 = 8, FIRSTDATA3 = 28+9 }
+		for (int i=0; i< ids.length; ++i) {
+			if (x==ids[i]) {
+				int level = i< FIRSTDATA2 ? 0: i<FIRSTDATA3 ? 1 : 2;
+				if (x==0x49 && family==0xF && model==0x6) level=2;
+				datacache[level].size=sizes[i];
+				datacache[level].associativity=ways[i];
+				if (level == 3 || x==0x2C || (x>=0x48 && x<=0x80) 
+                                   || x==0x86 || x==0x87
+                                   || (x>=0x66 && x<=0x68) || (x>=0x39 && x<=0x3E)){
+					datacache[level].lineSize = 64;
+				} else datacache[level].lineSize = 32;
+			}
+		}
+	}
+
+	uint[4] a;	
+	bool firstTime = true;
+	// On a multi-core system, this could theoretically fail, but it's only used
+	// for old single-core CPUs.
+	uint numinfos = 1;
+	do {
+		asm {
+			mov EAX, 2;
+			cpuid;
+			mov a, EAX;
+			mov a+4, EBX;
+			mov a+8, ECX;
+			mov a+12, EDX;
+		}
+		if (firstTime) {
+			if (a[0]==0x0000_7001 && a[3]==0x80 && a[1]==0 && a[2]==0) {
+		// Cyrix MediaGX MMXEnhanced returns: EAX= 00007001, EDX=00000080.
+		// These are NOT standard Intel values
+		// (TLB = 32 entry, 4 way associative, 4K pages)
+		// (L1 cache = 16K, 4way, linesize16)
+				datacache[0].size=8;
+				datacache[0].associativity=4;
+				datacache[0].lineSize=16;
+				return;				
+			}
+			// lsb of a is how many times to loop.
+			numinfos = a[0] & 0xFF;
+			// and otherwise it should be ignored
+			a[0] &= 0xFFFF_FF00;
+			firstTime = false;
+		}
+		for (int c=0; c<4;++c) {
+			// high bit set == no info.
+			if (a[c] & 0x8000_0000) continue;
+			decipherCpuid2(cast(ubyte)(a[c] & 0xFF));
+			decipherCpuid2(cast(ubyte)((a[c]>>8) & 0xFF));
+			decipherCpuid2(cast(ubyte)((a[c]>>16) & 0xFF));
+			decipherCpuid2(cast(ubyte)((a[c]>>24) & 0xFF));
+		}
+	} while (--numinfos);
+}
+
+// CPUID4: "Deterministic cache parameters" leaf
+void getcacheinfoCPUID4()
+{
+	int cachenum = 0;
+	for(;;) {
+		uint a, b, number_of_sets;	
+		asm {
+			mov EAX, 4;
+			mov ECX, cachenum;
+			cpuid;
+			mov a, EAX;
+			mov b, EBX;
+			mov number_of_sets, ECX;
+		}
+		++cachenum;
+		if ((a&0x1F)==0) break; // no more caches
+		uint numthreads = ((a>>14) & 0xFFF)  + 1;
+		uint numcores = ((a>>26) & 0x3F) + 1;
+		if (numcores > maxCores) maxCores = numcores;
+		if ((a&0x1F)!=1 && ((a&0x1F)!=3)) continue; // we only want data & unified caches
+		
+		++number_of_sets;
+		ubyte level = cast(ubyte)(((a>>5)&7)-1);
+		if (level > datacache.length) continue; // ignore deep caches
+		datacache[level].associativity = a & 0x200 ? ubyte.max :cast(ubyte)((b>>22)+1);
+		datacache[level].lineSize = (b & 0xFFF)+ 1; // system coherency line size
+		uint line_partitions = ((b >> 12)& 0x3FF) + 1;
+		// Size = number of sets * associativity * cachelinesize * linepartitions
+		// and must convert to Kb, also dividing by the number of hyperthreads using this cache.
+		ulong sz = (datacache[level].associativity< ubyte.max)? number_of_sets *
+			datacache[level].associativity : number_of_sets;		
+		datacache[level].size = cast(uint)(
+				(sz * datacache[level].lineSize * line_partitions ) / (numthreads *1024));
+		if (level == 0 && (a&0xF)==3) {
+			// Halve the size for unified L1 caches
+			datacache[level].size/=2;
+		}
+	}
+}
+
+// CPUID8000_0005 & 6
+void getAMDcacheinfo()
+{
+	uint c5, c6, d6;
+	asm {
+		mov EAX, 0x8000_0005; // L1 cache
+		cpuid;
+		// EAX has L1_TLB_4M.
+		// EBX has L1_TLB_4K
+		// EDX has L1 instruction cache
+		mov c5, ECX;
+	}
+
+	datacache[0].size = ( (c5>>24) & 0xFF);
+	datacache[0].associativity = cast(ubyte)( (c5 >> 16) & 0xFF);
+	datacache[0].lineSize = c5 & 0xFF;
+
+	if (max_extended_cpuid >= 0x8000_0006) {
+		// AMD K6-III or K6-2+ or later.
+		ubyte numcores = 1;
+		if (max_extended_cpuid >=0x8000_0008) {
+			asm {
+		    	mov EAX, 0x8000_0008;
+		    	cpuid;
+		    	mov numcores, CL;
+		    }
+		    ++numcores;
+		    if (numcores>maxCores) maxCores = numcores;
+		}
+		asm {
+			mov EAX, 0x8000_0006; // L2/L3 cache
+			cpuid;
+			mov c6, ECX; // L2 cache info
+			mov d6, EDX; // L3 cache info
+		}
+	
+		immutable ubyte [] assocmap = [ 0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 96, 128, 0xFF ];
+		datacache[1].size = (c6>>16) & 0xFFFF;
+		datacache[1].associativity = assocmap[(c6>>12)&0xF];
+		datacache[1].lineSize = c6 & 0xFF;
+		
+		// The L3 cache value is TOTAL, not per core.
+		datacache[2].size = ((d6>>18)*512)/numcores; // could be up to 2 * this, -1.
+		datacache[2].associativity = assocmap[(d6>>12)&0xF];
+		datacache[2].lineSize = d6 & 0xFF;
+	}
+}
+
+
+void cpuidX86()
+{
+    char * venptr = vendorID.ptr;
+	asm {
+		mov EAX, 0;
+		cpuid;
+		mov max_cpuid, EAX;
+		mov EAX, venptr;
+		mov [EAX], EBX;
+		mov [EAX + 4], EDX;
+		mov [EAX + 8], ECX;
+		mov EAX, 0x8000_0000;
+		cpuid;
+		mov max_extended_cpuid, EAX;
+	}
+	
+	probablyIntel = vendorID == "GenuineIntel";
+	probablyAMD = vendorID == "AuthenticAMD";
+	uint a, b, c, d;
+	uint apic = 0; // brand index, apic id
+	asm {
+		mov EAX, 1; // model, stepping
+		cpuid;
+		mov a, EAX;
+		mov apic, EBX;
+		mov miscfeatures, ECX;
+		mov features, EDX;
+	}
+	amdfeatures = 0;
+	amdmiscfeatures = 0;
+	if (max_extended_cpuid >= 0x8000_0001) {
+		asm {
+			mov EAX, 0x8000_0001;
+			cpuid;
+			mov amdmiscfeatures, ECX;
+			mov amdfeatures, EDX;
+		}
+	}
+	// Try to detect fraudulent vendorIDs
+	if (amd3dnow) probablyIntel = false;
+	
+	stepping = a & 0xF;
+	uint fbase = (a >> 8) & 0xF;
+	uint mbase = (a >> 4) & 0xF;
+	family = ((fbase == 0xF) || (fbase == 0)) ? fbase + (a >> 20) & 0xFF : fbase;
+	model = ((fbase == 0xF) || (fbase == 6 && probablyIntel) ) ?
+	     mbase + ((a >> 12) & 0xF0) : mbase;
+	     
+	if (!probablyIntel && max_extended_cpuid >= 0x8000_0008) {
+		// determine max number of cores for AMD
+		asm {
+			mov EAX, 0x8000_0008;
+			cpuid;
+			mov c, ECX;
+		}
+		uint apicsize = (c>>12) & 0xF;
+		if (apicsize == 0) {
+			// use legacy method
+			if (hyperThreadingBit)	maxCores = c & 0xFF;
+			else maxCores = 1;
+		} else {
+			// maxcores = 2^ apicsize
+			maxCores = 1;
+			while (apicsize) { maxCores<<=1; --apicsize; }
+		}
+	}
+	
+	if (max_extended_cpuid >= 0x8000_0004) {
+		char *procptr = processorNameBuffer.ptr;
+		asm {
+			push ESI;
+			mov ESI, procptr;
+			mov EAX, 0x8000_0002;
+			cpuid;
+			mov [ESI], EAX;
+			mov [ESI+4], EBX;
+			mov [ESI+8], ECX;
+			mov [ESI+12], EDX;
+			mov EAX, 0x8000_0003;
+			cpuid;
+			mov [ESI+16], EAX;
+			mov [ESI+20], EBX;
+			mov [ESI+24], ECX;
+			mov [ESI+28], EDX;
+			mov EAX, 0x8000_0004;
+			cpuid;
+			mov [ESI+32], EAX;
+			mov [ESI+36], EBX;
+			mov [ESI+40], ECX;
+			mov [ESI+44], EDX;
+			pop ESI;			
+		}
+		// Intel P4 and PM pad at front with spaces.
+		// Other CPUs pad at end with nulls.
+		int start = 0, end = 0;
+		while (processorNameBuffer[start] == ' ') { ++start; }
+		while (processorNameBuffer[$-end-1] == 0) { ++end; }
+		processorName = processorNameBuffer[start..$-end];
+	} else {
+		processorName[] = "Unknown CPU";
+	}
+	// Determine cache sizes
+	
+	// Intel docs specify that they return 0 for 0x8000_0005.
+	// AMD docs do not specify the behaviour for 0004 and 0002.
+	// Centaur/VIA and most other manufacturers use the AMD method,
+	// except Cyrix MediaGX MMX Enhanced uses their OWN form of CPUID2!
+	// NS Geode GX1 provides CyrixCPUID2 _and_ does the same wrong behaviour
+	// for CPUID80000005. But Geode GX uses the AMD method
+	
+	// Deal with Geode GX1 - make it same as MediaGX MMX.
+	if (max_extended_cpuid==0x8000_0005 && max_cpuid==2) {		
+		max_extended_cpuid = 0x8000_0004;
+	}
+	// Therefore, we try the AMD method unless it's an Intel chip.
+	// If we still have no info, try the Intel methods.
+	datacache[0].size = 0;
+	if (max_cpuid<2 || !probablyIntel) {
+		if (max_extended_cpuid >= 0x8000_0005) {
+			getAMDcacheinfo();
+		} else if (probablyAMD) {		
+			// According to AMDProcRecognitionAppNote, this means CPU
+			// K5 model 0, or Am5x86 (model 4), or Am4x86DX4 (model 4)
+			// Am5x86 has 16Kb 4-way unified data & code cache.
+			datacache[0].size = 8;
+			datacache[0].associativity = 4;
+			datacache[0].lineSize = 32;		
+		} else {
+			// Some obscure CPU.
+			// Values for Cyrix 6x86MX (family 6, model 0)
+			datacache[0].size = 64;
+			datacache[0].associativity = 4;
+			datacache[0].lineSize = 32;		
+		}
+	}	
+	if ((datacache[0].size == 0) && max_cpuid>=4) {
+		getcacheinfoCPUID4();
+	}
+	if ((datacache[0].size == 0) && max_cpuid>=2) {		
+		getcacheinfoCPUID2();
+	}
+	if (datacache[0].size == 0) {
+		// Pentium, PMMX, late model 486, or an obscure CPU
+		if (mmx) { // Pentium MMX. Also has 8kB code cache.
+			datacache[0].size = 16;
+			datacache[0].associativity = 4;
+			datacache[0].lineSize = 32;		
+		} else { // Pentium 1 (which also has 8kB code cache)
+				 // or 486.
+			// Cyrix 6x86: 16, 4way, 32 linesize
+			datacache[0].size = 8;
+			datacache[0].associativity = 2;
+			datacache[0].lineSize = 32;
+		}		
+	}
+	if (hyperThreadingBit) maxThreads = (apic>>>16) & 0xFF;
+	else maxThreads = maxCores;
+}
+
+// Return true if the cpuid instruction is supported.
+// BUG(WONTFIX): Returns false for Cyrix 6x86 and 6x86L. They will be treated as 486 machines.
+bool hasCPUID()
+{
+	uint flags;
+	asm {
+		pushfd;
+		pop EAX;
+		mov flags, EAX;
+		xor EAX, 0x0020_0000;
+		push EAX;
+		popfd;
+		pushfd;
+		pop EAX;
+		xor flags, EAX;
+	}
+	return (flags & 0x0020_0000) !=0;
+}
+
+} else { // inline asm X86
+
+	bool hasCPUID() { return false; }
+
+	void cpuidX86()
+	{
+			datacache[0].size = 8;
+			datacache[0].associativity = 2;
+			datacache[0].lineSize = 32;		
+	}	
+}
+
+// TODO: Implement this function with OS support
+void cpuidPPC()
+{
+	enum :int  { PPC601, PPC603, PPC603E, PPC604,
+	             PPC604E, PPC620, PPCG3, PPCG4, PPCG5 };
+
+	// TODO:
+	// asm { mfpvr; } returns the CPU version but unfortunately it can
+	// only be used in kernel mode. So OS support is required.
+	int cputype = PPC603;
+	
+	// 601 has a 8KB combined data & code L1 cache.
+	uint sizes[] = [4, 8, 16, 16, 32, 32, 32, 32, 64];
+	ubyte ways[] = [8, 2,  4,  4,  4,  8,  8,  8,  8];
+	uint L2size[]= [0, 0,  0,  0,  0,  0,  0,  256,  512];
+	uint L3size[]= [0, 0,  0,  0,  0,  0,  0,  2048,  0];
+    
+	datacache[0].size = sizes[cputype];
+	datacache[0].associativity = ways[cputype]; 
+	datacache[0].lineSize = (cputype==PPCG5)? 128 : 
+		(cputype == PPC620 || cputype == PPCG3)? 64 : 32;
+	datacache[1].size = L2size[cputype];
+	datacache[2].size = L3size[cputype];
+	datacache[1].lineSize = datacache[0].lineSize;
+	datacache[2].lineSize = datacache[0].lineSize;
+}
+
+// TODO: Implement this function with OS support
+void cpuidSparc()
+{
+	// UltaSparcIIi  : L1 = 16,  2way. L2 = 512, 4 way.
+	// UltraSparcIII : L1 = 64,  4way. L2= 4096 or 8192.
+	// UltraSparcIIIi: L1 = 64,  4way. L2= 1024, 4 way
+	// UltraSparcIV  : L1 = 64,  4way. L2 = 16*1024.
+	// UltraSparcIV+ : L1 = 64,  4way. L2 = 2048, L3=32*1024.
+	// Sparc64V      : L1 = 128, 2way. L2 = 4096 4way.	
+}
+
+
+static this()
+{
+	if (hasCPUID()) {
+		cpuidX86();
+	} else {
+		// it's a 386 or 486, or a Cyrix 6x86.
+		//Probably still has an external cache.
+	}
+	if (datacache[0].size==0) {
+			// Guess same as Pentium 1.
+			datacache[0].size = 8;
+			datacache[0].associativity = 2;
+			datacache[0].lineSize = 32;		
+	}
+	numCacheLevels = 1;
+	// And now fill up all the unused levels with full memory space.
+	for (int i=1; i< datacache.length; ++i) {
+		if (datacache[i].size==0) {
+			// Set all remaining levels of cache equal to full address space.
+			datacache[i].size = uint.max/1024;
+			datacache[i].associativity = 1;
+			datacache[i].lineSize = datacache[i-1].lineSize;
+		} else numCacheLevels = i+1;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/util/ctype.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,92 @@
+/**
+ * Simple ASCII char classification functions.
+ *
+ * Copyright: Copyright Digital Mars 2004 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright
+ *
+ *          Copyright Digital Mars 2004 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.util.ctype;
+
+int isalnum(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG) : 0; }
+int isalpha(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP)      : 0; }
+int iscntrl(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_CTL)      : 0; }
+int isdigit(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_DIG)      : 0; }
+int islower(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_LC)       : 0; }
+int ispunct(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_PNC)      : 0; }
+int isspace(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_SPC)      : 0; }
+int isupper(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_UC)       : 0; }
+int isxdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_HEX)      : 0; }
+int isgraph(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC) : 0; }
+int isprint(dchar c)  { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC|_BLK) : 0; }
+int isascii(dchar c)  { return c <= 0x7F; }
+
+dchar tolower(dchar c)
+out (result)
+{
+    assert(!isupper(result));
+}
+body
+{
+    return isupper(c) ? c + (cast(dchar)'a' - 'A') : c;
+}
+
+dchar toupper(dchar c)
+out (result)
+{
+    assert(!islower(result));
+}
+body
+{
+    return islower(c) ? c - (cast(dchar)'a' - 'A') : c;
+}
+
+private:
+
+enum
+{
+    _SPC =	8,
+    _CTL =	0x20,
+    _BLK =	0x40,
+    _HEX =	0x80,
+    _UC  =	1,
+    _LC  =	2,
+    _PNC =	0x10,
+    _DIG =	4,
+    _ALP =	_UC|_LC,
+}
+
+immutable ubyte _ctype[128] =
+[
+	_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
+	_CTL,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL,_CTL,
+	_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
+	_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
+	_SPC|_BLK,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
+	_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
+	_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_PNC,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC,
+	_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
+	_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
+	_UC,_UC,_UC,_PNC,_PNC,_PNC,_PNC,_PNC,
+	_PNC,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC,
+	_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
+	_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
+	_LC,_LC,_LC,_PNC,_PNC,_PNC,_PNC,_CTL
+];
+
+
+unittest
+{
+    assert(isspace(' '));
+    assert(!isspace('z'));
+    assert(toupper('a') == 'A');
+    assert(tolower('Q') == 'q');
+    assert(!isxdigit('G'));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/util/string.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,40 @@
+/**
+ * The exception module defines all system-level exceptions and provides a
+ * mechanism to alter system-level error handling.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.util.string;
+
+private import core.stdc.string;
+
+char[] intToString( char[] buf, uint val )
+{
+    assert( buf.length > 9 );
+    auto p = buf.ptr + buf.length;
+
+    do
+    {
+        *--p = cast(char)(val % 10 + '0');
+    } while( val /= 10 );
+
+    return buf[p - buf.ptr .. $];
+}
+
+
+int dstrcmp( in char[] s1, in char[] s2 )
+{
+    auto len = s1.length;
+    if( s2.length < len )
+        len = s2.length;
+    if( memcmp( s1.ptr, s2.ptr, len ) == 0 )
+        return 0;
+    return s1.length > s2.length ? 1 : -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/util/utf.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,901 @@
+/********************************************
+ * Encode and decode UTF-8, UTF-16 and UTF-32 strings.
+ *
+ * For Win32 systems, the C wchar_t type is UTF-16 and corresponds to the D
+ * wchar type.
+ * For Posix systems, the C wchar_t type is UTF-32 and corresponds to
+ * the D utf.dchar type.
+ *
+ * UTF character support is restricted to (\u0000 &lt;= character &lt;= \U0010FFFF).
+ *
+ * See_Also:
+ *	$(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia)<br>
+ *	$(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)<br>
+ *	$(LINK http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335)
+ * Macros:
+ *	WIKI = Phobos/StdUtf
+ *
+ * Copyright: Copyright Digital Mars 2003 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2003 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module rt.util.utf;
+
+
+extern (C) void onUnicodeError( string msg, size_t idx );
+
+/*******************************
+ * Test if c is a valid UTF-32 character.
+ *
+ * \uFFFE and \uFFFF are considered valid by this function,
+ * as they are permitted for internal use by an application,
+ * but they are not allowed for interchange by the Unicode standard.
+ *
+ * Returns: true if it is, false if not.
+ */
+
+bool isValidDchar(dchar c)
+{
+    /* Note: FFFE and FFFF are specifically permitted by the
+     * Unicode standard for application internal use, but are not
+     * allowed for interchange.
+     * (thanks to Arcane Jill)
+     */
+
+    return c < 0xD800 ||
+	(c > 0xDFFF && c <= 0x10FFFF /*&& c != 0xFFFE && c != 0xFFFF*/);
+}
+
+unittest
+{
+    debug(utf) printf("utf.isValidDchar.unittest\n");
+    assert(isValidDchar(cast(dchar)'a') == true);
+    assert(isValidDchar(cast(dchar)0x1FFFFF) == false);
+}
+
+
+
+immutable UTF8stride =
+[
+    cast(ubyte)
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+    4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF,
+];
+
+/**
+ * stride() returns the length of a UTF-8 sequence starting at index i
+ * in string s.
+ * Returns:
+ *	The number of bytes in the UTF-8 sequence or
+ *	0xFF meaning s[i] is not the start of of UTF-8 sequence.
+ */
+uint stride(in char[] s, size_t i)
+{
+    return UTF8stride[s[i]];
+}
+
+/**
+ * stride() returns the length of a UTF-16 sequence starting at index i
+ * in string s.
+ */
+uint stride(in wchar[] s, size_t i)
+{   uint u = s[i];
+    return 1 + (u >= 0xD800 && u <= 0xDBFF);
+}
+
+/**
+ * stride() returns the length of a UTF-32 sequence starting at index i
+ * in string s.
+ * Returns: The return value will always be 1.
+ */
+uint stride(in dchar[] s, size_t i)
+{
+    return 1;
+}
+
+/*******************************************
+ * Given an index i into an array of characters s[],
+ * and assuming that index i is at the start of a UTF character,
+ * determine the number of UCS characters up to that index i.
+ */
+
+size_t toUCSindex(in char[] s, size_t i)
+{
+    size_t n;
+    size_t j;
+
+    for (j = 0; j < i; )
+    {
+	j += stride(s, j);
+	n++;
+    }
+    if (j > i)
+    {
+        onUnicodeError("invalid UTF-8 sequence", j);
+    }
+    return n;
+}
+
+/** ditto */
+size_t toUCSindex(in wchar[] s, size_t i)
+{
+    size_t n;
+    size_t j;
+
+    for (j = 0; j < i; )
+    {
+	j += stride(s, j);
+	n++;
+    }
+    if (j > i)
+    {
+        onUnicodeError("invalid UTF-16 sequence", j);
+    }
+    return n;
+}
+
+/** ditto */
+size_t toUCSindex(in dchar[] s, size_t i)
+{
+    return i;
+}
+
+/******************************************
+ * Given a UCS index n into an array of characters s[], return the UTF index.
+ */
+
+size_t toUTFindex(in char[] s, size_t n)
+{
+    size_t i;
+
+    while (n--)
+    {
+	uint j = UTF8stride[s[i]];
+	if (j == 0xFF)
+	    onUnicodeError("invalid UTF-8 sequence", i);
+	i += j;
+    }
+    return i;
+}
+
+/** ditto */
+size_t toUTFindex(in wchar[] s, size_t n)
+{
+    size_t i;
+
+    while (n--)
+    {	wchar u = s[i];
+
+	i += 1 + (u >= 0xD800 && u <= 0xDBFF);
+    }
+    return i;
+}
+
+/** ditto */
+size_t toUTFindex(in dchar[] s, size_t n)
+{
+    return n;
+}
+
+/* =================== Decode ======================= */
+
+/***************
+ * Decodes and returns character starting at s[idx]. idx is advanced past the
+ * decoded character. If the character is not well formed, a UtfException is
+ * thrown and idx remains unchanged.
+ */
+dchar decode(in char[] s, inout size_t idx)
+    in
+    {
+	assert(idx >= 0 && idx < s.length);
+    }
+    out (result)
+    {
+	assert(isValidDchar(result));
+    }
+    body
+    {
+	size_t len = s.length;
+	dchar V;
+	size_t i = idx;
+	char u = s[i];
+
+	if (u & 0x80)
+	{   uint n;
+	    char u2;
+
+	    /* The following encodings are valid, except for the 5 and 6 byte
+	     * combinations:
+	     *	0xxxxxxx
+	     *	110xxxxx 10xxxxxx
+	     *	1110xxxx 10xxxxxx 10xxxxxx
+	     *	11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+	     *	111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+	     *	1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+	     */
+	    for (n = 1; ; n++)
+	    {
+		if (n > 4)
+		    goto Lerr;		// only do the first 4 of 6 encodings
+		if (((u << n) & 0x80) == 0)
+		{
+		    if (n == 1)
+			goto Lerr;
+		    break;
+		}
+	    }
+
+	    // Pick off (7 - n) significant bits of B from first byte of octet
+	    V = cast(dchar)(u & ((1 << (7 - n)) - 1));
+
+	    if (i + (n - 1) >= len)
+		goto Lerr;			// off end of string
+
+	    /* The following combinations are overlong, and illegal:
+	     *	1100000x (10xxxxxx)
+	     *	11100000 100xxxxx (10xxxxxx)
+	     *	11110000 1000xxxx (10xxxxxx 10xxxxxx)
+	     *	11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
+	     *	11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
+	     */
+	    u2 = s[i + 1];
+	    if ((u & 0xFE) == 0xC0 ||
+		(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
+		(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
+		(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
+		(u == 0xFC && (u2 & 0xFC) == 0x80))
+		goto Lerr;			// overlong combination
+
+	    for (uint j = 1; j != n; j++)
+	    {
+		u = s[i + j];
+		if ((u & 0xC0) != 0x80)
+		    goto Lerr;			// trailing bytes are 10xxxxxx
+		V = (V << 6) | (u & 0x3F);
+	    }
+	    if (!isValidDchar(V))
+		goto Lerr;
+	    i += n;
+	}
+	else
+	{
+	    V = cast(dchar) u;
+	    i++;
+	}
+
+	idx = i;
+	return V;
+
+      Lerr:
+      onUnicodeError("invalid UTF-8 sequence", i);
+    return V; // dummy return
+    }
+
+unittest
+{   size_t i;
+    dchar c;
+
+    debug(utf) printf("utf.decode.unittest\n");
+
+    static s1 = "abcd"c;
+    i = 0;
+    c = decode(s1, i);
+    assert(c == cast(dchar)'a');
+    assert(i == 1);
+    c = decode(s1, i);
+    assert(c == cast(dchar)'b');
+    assert(i == 2);
+
+    static s2 = "\xC2\xA9"c;
+    i = 0;
+    c = decode(s2, i);
+    assert(c == cast(dchar)'\u00A9');
+    assert(i == 2);
+
+    static s3 = "\xE2\x89\xA0"c;
+    i = 0;
+    c = decode(s3, i);
+    assert(c == cast(dchar)'\u2260');
+    assert(i == 3);
+
+    static s4 =
+    [	"\xE2\x89"c[],		// too short
+	"\xC0\x8A",
+	"\xE0\x80\x8A",
+	"\xF0\x80\x80\x8A",
+	"\xF8\x80\x80\x80\x8A",
+	"\xFC\x80\x80\x80\x80\x8A",
+    ];
+
+    for (int j = 0; j < s4.length; j++)
+    {
+	try
+	{
+	    i = 0;
+	    c = decode(s4[j], i);
+	    assert(0);
+	}
+	catch (Object o)
+	{
+	    i = 23;
+	}
+	assert(i == 23);
+    }
+}
+
+/** ditto */
+
+dchar decode(in wchar[] s, inout size_t idx)
+    in
+    {
+	assert(idx >= 0 && idx < s.length);
+    }
+    out (result)
+    {
+	assert(isValidDchar(result));
+    }
+    body
+    {
+	string msg;
+	dchar V;
+	size_t i = idx;
+	uint u = s[i];
+
+	if (u & ~0x7F)
+	{   if (u >= 0xD800 && u <= 0xDBFF)
+	    {   uint u2;
+
+		if (i + 1 == s.length)
+		{   msg = "surrogate UTF-16 high value past end of string";
+		    goto Lerr;
+		}
+		u2 = s[i + 1];
+		if (u2 < 0xDC00 || u2 > 0xDFFF)
+		{   msg = "surrogate UTF-16 low value out of range";
+		    goto Lerr;
+		}
+		u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00);
+		i += 2;
+	    }
+	    else if (u >= 0xDC00 && u <= 0xDFFF)
+	    {   msg = "unpaired surrogate UTF-16 value";
+		goto Lerr;
+	    }
+	    else if (u == 0xFFFE || u == 0xFFFF)
+	    {   msg = "illegal UTF-16 value";
+		goto Lerr;
+	    }
+	    else
+		i++;
+	}
+	else
+	{
+	    i++;
+	}
+
+	idx = i;
+	return cast(dchar)u;
+
+      Lerr:
+	  onUnicodeError(msg, i);
+	return cast(dchar)u; // dummy return
+    }
+
+/** ditto */
+
+dchar decode(in dchar[] s, inout size_t idx)
+    in
+    {
+	assert(idx >= 0 && idx < s.length);
+    }
+    body
+    {
+	size_t i = idx;
+	dchar c = s[i];
+
+	if (!isValidDchar(c))
+	    goto Lerr;
+	idx = i + 1;
+	return c;
+
+      Lerr:
+	  onUnicodeError("invalid UTF-32 value", i);
+	return c; // dummy return
+    }
+
+
+/* =================== Encode ======================= */
+
+/*******************************
+ * Encodes character c and appends it to array s[].
+ */
+void encode(inout char[] s, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	char[] r = s;
+
+	if (c <= 0x7F)
+	{
+	    r ~= cast(char) c;
+	}
+	else
+	{
+	    char[4] buf;
+	    uint L;
+
+	    if (c <= 0x7FF)
+	    {
+		buf[0] = cast(char)(0xC0 | (c >> 6));
+		buf[1] = cast(char)(0x80 | (c & 0x3F));
+		L = 2;
+	    }
+	    else if (c <= 0xFFFF)
+	    {
+		buf[0] = cast(char)(0xE0 | (c >> 12));
+		buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+		buf[2] = cast(char)(0x80 | (c & 0x3F));
+		L = 3;
+	    }
+	    else if (c <= 0x10FFFF)
+	    {
+		buf[0] = cast(char)(0xF0 | (c >> 18));
+		buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
+		buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+		buf[3] = cast(char)(0x80 | (c & 0x3F));
+		L = 4;
+	    }
+	    else
+	    {
+		assert(0);
+	    }
+	    r ~= buf[0 .. L];
+	}
+	s = r;
+    }
+
+unittest
+{
+    debug(utf) printf("utf.encode.unittest\n");
+
+    char[] s = "abcd".dup;
+    encode(s, cast(dchar)'a');
+    assert(s.length == 5);
+    assert(s == "abcda");
+
+    encode(s, cast(dchar)'\u00A9');
+    assert(s.length == 7);
+    assert(s == "abcda\xC2\xA9");
+    //assert(s == "abcda\u00A9");	// BUG: fix compiler
+
+    encode(s, cast(dchar)'\u2260');
+    assert(s.length == 10);
+    assert(s == "abcda\xC2\xA9\xE2\x89\xA0");
+}
+
+/** ditto */
+
+void encode(inout wchar[] s, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	wchar[] r = s;
+
+	if (c <= 0xFFFF)
+	{
+	    r ~= cast(wchar) c;
+	}
+	else
+	{
+	    wchar[2] buf;
+
+	    buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
+	    buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
+	    r ~= buf;
+	}
+	s = r;
+    }
+
+/** ditto */
+void encode(inout dchar[] s, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	s ~= c;
+    }
+
+/**
+Returns the code length of $(D c) in the encoding using $(D C) as a
+code point. The code is returned in character count, not in bytes.
+ */
+
+ubyte codeLength(C)(dchar c)
+{
+
+    static if (C.sizeof == 1)
+    {
+        return
+            c <= 0x7F ? 1
+            : c <= 0x7FF ? 2
+            : c <= 0xFFFF ? 3
+            : c <= 0x10FFFF ? 4
+            : (assert(false), 6);
+}
+
+    else static if (C.sizeof == 2)
+{
+	return c <= 0xFFFF ? 1 : 2;
+    }
+    else
+    {
+        static assert(C.sizeof == 4);
+        return 1;
+    }
+}
+
+/* =================== Validation ======================= */
+
+/***********************************
+Checks to see if string is well formed or not. $(D S) can be an array
+ of $(D char), $(D wchar), or $(D dchar). Throws a $(D UtfException)
+ if it is not. Use to check all untrusted input for correctness.
+ */
+void validate(S)(in S s)
+{
+    auto len = s.length;
+    for (size_t i = 0; i < len; )
+    {
+	decode(s, i);
+    }
+}
+
+/* =================== Conversion to UTF8 ======================= */
+
+char[] toUTF8(char[4] buf, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	if (c <= 0x7F)
+	{
+	    buf[0] = cast(char) c;
+	    return buf[0 .. 1];
+	}
+	else if (c <= 0x7FF)
+	{
+	    buf[0] = cast(char)(0xC0 | (c >> 6));
+	    buf[1] = cast(char)(0x80 | (c & 0x3F));
+	    return buf[0 .. 2];
+	}
+	else if (c <= 0xFFFF)
+	{
+	    buf[0] = cast(char)(0xE0 | (c >> 12));
+	    buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+	    buf[2] = cast(char)(0x80 | (c & 0x3F));
+	    return buf[0 .. 3];
+	}
+	else if (c <= 0x10FFFF)
+	{
+	    buf[0] = cast(char)(0xF0 | (c >> 18));
+	    buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
+	    buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
+	    buf[3] = cast(char)(0x80 | (c & 0x3F));
+	    return buf[0 .. 4];
+	}
+	assert(0);
+    }
+
+/*******************
+ * Encodes string s into UTF-8 and returns the encoded string.
+ */
+string toUTF8(string s)
+    in
+    {
+	validate(s);
+    }
+    body
+    {
+	return s;
+    }
+
+/** ditto */
+string toUTF8(in wchar[] s)
+{
+    char[] r;
+    size_t i;
+    size_t slen = s.length;
+
+    r.length = slen;
+
+    for (i = 0; i < slen; i++)
+    {	wchar c = s[i];
+
+	if (c <= 0x7F)
+	    r[i] = cast(char)c;		// fast path for ascii
+	else
+	{
+	    r.length = i;
+	    foreach (dchar c; s[i .. slen])
+	    {
+		encode(r, c);
+	    }
+	    break;
+	}
+    }
+    return cast(string)r;
+}
+
+/** ditto */
+string toUTF8(in dchar[] s)
+{
+    char[] r;
+    size_t i;
+    size_t slen = s.length;
+
+    r.length = slen;
+
+    for (i = 0; i < slen; i++)
+    {	dchar c = s[i];
+
+	if (c <= 0x7F)
+	    r[i] = cast(char)c;		// fast path for ascii
+	else
+	{
+	    r.length = i;
+	    foreach (dchar d; s[i .. slen])
+	    {
+		encode(r, d);
+	    }
+	    break;
+	}
+    }
+    return cast(string)r;
+}
+
+/* =================== Conversion to UTF16 ======================= */
+
+wchar[] toUTF16(wchar[2] buf, dchar c)
+    in
+    {
+	assert(isValidDchar(c));
+    }
+    body
+    {
+	if (c <= 0xFFFF)
+	{
+	    buf[0] = cast(wchar) c;
+	    return buf[0 .. 1];
+	}
+	else
+	{
+	    buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
+	    buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
+	    return buf[0 .. 2];
+	}
+    }
+
+/****************
+ * Encodes string s into UTF-16 and returns the encoded string.
+ * toUTF16z() is suitable for calling the 'W' functions in the Win32 API that take
+ * an LPWSTR or LPCWSTR argument.
+ */
+wstring toUTF16(in char[] s)
+{
+    wchar[] r;
+    size_t slen = s.length;
+
+    r.length = slen;
+    r.length = 0;
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c <= 0x7F)
+	{
+	    i++;
+	    r ~= cast(wchar)c;
+	}
+	else
+	{
+	    c = decode(s, i);
+	    encode(r, c);
+	}
+    }
+    return cast(wstring)r;
+}
+
+alias const(wchar)* wptr;
+/** ditto */
+wptr toUTF16z(in char[] s)
+{
+    wchar[] r;
+    size_t slen = s.length;
+
+    r.length = slen + 1;
+    r.length = 0;
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c <= 0x7F)
+	{
+	    i++;
+	    r ~= cast(wchar)c;
+	}
+	else
+	{
+	    c = decode(s, i);
+	    encode(r, c);
+	}
+    }
+    r ~= "\000";
+    return r.ptr;
+}
+
+/** ditto */
+wstring toUTF16(wstring s)
+    in
+    {
+	validate(s);
+    }
+    body
+    {
+	return s;
+    }
+
+/** ditto */
+wstring toUTF16(in dchar[] s)
+{
+    wchar[] r;
+    size_t slen = s.length;
+
+    r.length = slen;
+    r.length = 0;
+    for (size_t i = 0; i < slen; i++)
+    {
+	encode(r, s[i]);
+    }
+    return cast(wstring)r;
+}
+
+/* =================== Conversion to UTF32 ======================= */
+
+/*****
+ * Encodes string s into UTF-32 and returns the encoded string.
+ */
+dstring toUTF32(in char[] s)
+{
+    dchar[] r;
+    size_t slen = s.length;
+    size_t j = 0;
+
+    r.length = slen;		// r[] will never be longer than s[]
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c >= 0x80)
+	    c = decode(s, i);
+	else
+	    i++;		// c is ascii, no need for decode
+	r[j++] = c;
+    }
+    return cast(dstring)r[0 .. j];
+}
+
+/** ditto */
+dstring toUTF32(in wchar[] s)
+{
+    dchar[] r;
+    size_t slen = s.length;
+    size_t j = 0;
+
+    r.length = slen;		// r[] will never be longer than s[]
+    for (size_t i = 0; i < slen; )
+    {
+	dchar c = s[i];
+	if (c >= 0x80)
+	    c = decode(s, i);
+	else
+	    i++;		// c is ascii, no need for decode
+	r[j++] = c;
+    }
+    return cast(dstring)r[0 .. j];
+}
+
+/** ditto */
+dstring toUTF32(dstring s)
+    in
+    {
+	validate(s);
+    }
+    body
+    {
+	return s;
+    }
+
+/* ================================ tests ================================== */
+
+unittest
+{
+    debug(utf) printf("utf.toUTF.unittest\n");
+
+    auto c = "hello"c[];
+    auto w = toUTF16(c);
+    assert(w == "hello");
+    auto d = toUTF32(c);
+    assert(d == "hello");
+
+    c = toUTF8(w);
+    assert(c == "hello");
+    d = toUTF32(w);
+    assert(d == "hello");
+
+    c = toUTF8(d);
+    assert(c == "hello");
+    w = toUTF16(d);
+    assert(w == "hello");
+
+
+    c = "hel\u1234o";
+    w = toUTF16(c);
+    assert(w == "hel\u1234o");
+    d = toUTF32(c);
+    assert(d == "hel\u1234o");
+
+    c = toUTF8(w);
+    assert(c == "hel\u1234o");
+    d = toUTF32(w);
+    assert(d == "hel\u1234o");
+
+    c = toUTF8(d);
+    assert(c == "hel\u1234o");
+    w = toUTF16(d);
+    assert(w == "hel\u1234o");
+
+
+    c = "he\U0010AAAAllo";
+    w = toUTF16(c);
+    //foreach (wchar c; w) printf("c = x%x\n", c);
+    //foreach (wchar c; cast(wstring)"he\U0010AAAAllo") printf("c = x%x\n", c);
+    assert(w == "he\U0010AAAAllo");
+    d = toUTF32(c);
+    assert(d == "he\U0010AAAAllo");
+
+    c = toUTF8(w);
+    assert(c == "he\U0010AAAAllo");
+    d = toUTF32(w);
+    assert(d == "he\U0010AAAAllo");
+
+    c = toUTF8(d);
+    assert(c == "he\U0010AAAAllo");
+    w = toUTF16(d);
+    assert(w == "he\U0010AAAAllo");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/compiler/ldc/win32.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,175 @@
+# Makefile to build the D runtime library core components for Posix
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR=..\..\..\lib
+DOCDIR=..\..\..\doc
+IMPDIR=..\..\..\import
+LIBBASENAME=druntime_rt_dmd.lib
+#MODULES=bitop exception memory runtime thread vararg \
+#	$(addprefix sync/,barrier condition config exception mutex rwmutex semaphore)
+BUILDS=debug release unittest
+
+MODULES_BASE= \
+	aaA.d \
+	aApply.d \
+	aApplyR.d \
+	adi.d \
+	arrayassign.d \
+	arraybyte.d \
+	arraycast.d \
+	arraycat.d \
+	arraydouble.d \
+	arrayfloat.d \
+	arrayint.d \
+	arrayreal.d \
+	arrayshort.d \
+	cast_.d \
+	cover.d \
+	dmain2.d \
+	invariant.d \
+	invariant_.d \
+	lifetime.d \
+	memory.d \
+	memset.d \
+	obj.d \
+	object_.d \
+	qsort.d \
+	switch_.d \
+	trace.d
+# NOTE: trace.d and cover.d are not necessary for a successful build
+#       as both are used for debugging features (profiling and coverage)
+# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and
+#       minit.asm is not used by dmd for Linux
+
+MODULES_UTIL= \
+	util\console.d \
+	util\cpuid.d \
+	util\ctype.d \
+	util\string.d \
+	util\utf.d
+
+MODULES_TI= \
+	typeinfo\ti_AC.d \
+	typeinfo\ti_Acdouble.d \
+	typeinfo\ti_Acfloat.d \
+	typeinfo\ti_Acreal.d \
+	typeinfo\ti_Adouble.d \
+	typeinfo\ti_Afloat.d \
+	typeinfo\ti_Ag.d \
+	typeinfo\ti_Aint.d \
+	typeinfo\ti_Along.d \
+	typeinfo\ti_Areal.d \
+	typeinfo\ti_Ashort.d \
+	typeinfo\ti_byte.d \
+	typeinfo\ti_C.d \
+	typeinfo\ti_cdouble.d \
+	typeinfo\ti_cfloat.d \
+	typeinfo\ti_char.d \
+	typeinfo\ti_creal.d \
+	typeinfo\ti_dchar.d \
+	typeinfo\ti_delegate.d \
+	typeinfo\ti_double.d \
+	typeinfo\ti_float.d \
+	typeinfo\ti_idouble.d \
+	typeinfo\ti_ifloat.d \
+	typeinfo\ti_int.d \
+	typeinfo\ti_ireal.d \
+	typeinfo\ti_long.d \
+	typeinfo\ti_ptr.d \
+	typeinfo\ti_real.d \
+	typeinfo\ti_short.d \
+	typeinfo\ti_ubyte.d \
+	typeinfo\ti_uint.d \
+	typeinfo\ti_ulong.d \
+	typeinfo\ti_ushort.d \
+	typeinfo\ti_void.d \
+	typeinfo\ti_wchar.d
+
+C_SRCS=complex.c critical.c deh.c monitor.c
+
+# Symbols
+
+CC=dmc
+DMD=dmd
+DOCFLAGS=-version=DDoc
+DFLAGS_release=-d -release -O -inline -w -nofloat
+DFLAGS_debug=-d -g -w -nofloat
+DFLAGS_unittest=$(DFLAGS_release) -unittest
+CFLAGS_release=-mn -6 -r
+CFLAGS_debug=-g -mn -6 -r
+CFLAGS_unittest=$(CFLAGS_release)
+
+# Derived symbols
+
+C_OBJS=complex.obj critical.obj deh.obj monitor.obj
+AS_OBJS=minit.obj
+ALL_MODULES=$(MODULES_BASE) $(MODULES_UTIL) $(MODULES_TI)
+D_SRCS=$(ALL_MODULES)
+ALLLIBS=\
+	$(LIBDIR)\debug\$(LIBBASENAME) \
+	$(LIBDIR)\release\$(LIBBASENAME) \
+	$(LIBDIR)\unittest\$(LIBBASENAME)
+
+# Patterns
+
+#$(LIBDIR)\%\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS)
+#	$(CC) -c $(CFLAGS_$*) $(C_SRCS)
+#	$(DMD) $(DFLAGS_$*) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS)
+#	del $(C_OBJS)
+
+#$(DOCDIR)\%.html : %.d
+#	$(DMD) -c -d -o- -Df$@ $<
+
+#$(IMPDIR)\%.di : %.d
+#	$(DMD) -c -d -o- -Hf$@ $<
+
+# Patterns - debug
+
+$(LIBDIR)\debug\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS)
+	$(CC) -c $(CFLAGS_debug) $(C_SRCS)
+	$(DMD) $(DFLAGS_debug) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS)
+	del $(C_OBJS)
+
+# Patterns - release
+
+$(LIBDIR)\release\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS)
+	$(CC) -c $(CFLAGS_release) $(C_SRCS)
+	$(DMD) $(DFLAGS_release) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS)
+	del $(C_OBJS)
+
+# Patterns - unittest
+
+$(LIBDIR)\unittest\$(LIBBASENAME) : $(D_SRCS) $(C_SRCS) $(AS_OBJS)
+	$(CC) -c $(CFLAGS_unittest) $(C_SRCS)
+	$(DMD) $(DFLAGS_unittest) -lib -of$@ $(D_SRCS) $(C_OBJS) $(AS_OBJS)
+	del $(C_OBJS)
+
+# Patterns - asm
+
+minit.obj : minit.asm
+	$(CC) -c $**
+
+# Rulez
+
+all : $(BUILDS) doc
+
+debug : $(LIBDIR)\debug\$(LIBBASENAME) $(IMPORTS)
+release : $(LIBDIR)\release\$(LIBBASENAME) $(IMPORTS)
+unittest : $(LIBDIR)\unittest\$(LIBBASENAME) $(IMPORTS)
+#doc : $(DOCS)
+
+clean :
+	del $(IMPORTS) $(DOCS) $(ALLLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/dmd-posix.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,72 @@
+# Makefile to build the composite D runtime library for Linux
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR:=../lib
+DOCDIR:=../doc
+LIBBASENAME=libdruntime.a
+
+DIR_CC=common
+DIR_RT=compiler/dmd
+DIR_GC=gc/basic
+
+# Symbols
+
+DMD=dmd
+
+# Targets
+
+all : debug release doc unittest $(LIBDIR)/$(LIBBASENAME)
+
+# unittest :
+# 	$(MAKE) -fdmd-posix.mak lib MAKE_LIB="unittest"
+# 	dmd -unittest unittest ../import/core/stdc/stdarg \
+# 		-defaultlib="$(DUP_TARGET)" -debuglib="$(DUP_TARGET)"
+# 	$(RM) stdarg.o
+# 	./unittest
+
+debug release unittest :
+	@$(MAKE) DMD=$(DMD) -C $(DIR_CC) --no-print-directory -fposix.mak $@
+	@$(MAKE) DMD=$(DMD) -C $(DIR_RT) --no-print-directory -fposix.mak $@
+	@$(MAKE) DMD=$(DMD) -C $(DIR_GC) --no-print-directory -fposix.mak $@
+	@$(DMD) -lib -of$(LIBDIR)/$@/$(LIBBASENAME) \
+		$(LIBDIR)/$@/libdruntime-core.a \
+		$(LIBDIR)/$@/libdruntime-rt-dmd.a \
+		$(LIBDIR)/$@/libdruntime-gc-basic.a
+
+$(LIBDIR)/$(LIBBASENAME) : $(LIBDIR)/release/$(LIBBASENAME)
+	ln -sf $(realpath $<) $@
+
+doc : $(ALL_DOCS)
+	$(MAKE) DMD=$(DMD) -C $(DIR_CC) --no-print-directory -fposix.mak doc
+#	$(MAKE) DMD=$(DMD) -C $(DIR_RT) --no-print-directory -fposix.mak doc
+#	$(MAKE) DMD=$(DMD) -C $(DIR_GC) --no-print-directory -fposix.mak doc
+
+######################################################
+
+clean :
+	$(MAKE) DMD=$(DMD) -C $(DIR_CC) --no-print-directory -fposix.mak clean
+	$(MAKE) DMD=$(DMD) -C $(DIR_RT) --no-print-directory -fposix.mak clean
+	$(MAKE) DMD=$(DMD) -C $(DIR_GC) --no-print-directory -fposix.mak clean
+#find . -name "*.di" | xargs $(RM)
+	rm -rf $(LIBDIR) $(DOCDIR)
+
+# install :
+# 	make -C $(DIR_CC) --no-print-directory -fposix.mak install
+# 	make -C $(DIR_RT) --no-print-directory -fposix.mak install
+# 	make -C $(DIR_GC) --no-print-directory -fposix.mak install
+# 	$(CP) $(LIB_MASK) $(LIB_DEST)/.
+# 	$(CP) $(DUP_MASK) $(LIB_DEST)/.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/dmd-win32.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,89 @@
+# Makefile to build the composite D runtime library for Linux
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR=..\lib
+DOCDIR=..\doc
+LIBBASENAME=druntime.lib
+
+DIR_CC=common
+DIR_RT=compiler\dmd
+DIR_GC=gc\basic
+
+# Symbols
+
+DMD=dmd
+
+# Targets
+
+all : debug release doc unittest $(LIBDIR)\$(LIBBASENAME)
+
+# unittest :
+# 	$(MAKE) -fdmd-posix.mak lib MAKE_LIB="unittest"
+# 	dmd -unittest unittest ../import/core/stdc/stdarg \
+# 		-defaultlib="$(DUP_TARGET)" -debuglib="$(DUP_TARGET)"
+# 	$(RM) stdarg.o
+# 	./unittest
+
+debug release unittest :
+	cd $(DIR_CC)
+	make DMD=$(DMD) -fwin32.mak $@
+	cd ..
+	cd $(DIR_RT)
+	make DMD=$(DMD) -fwin32.mak $@
+	cd ..\..
+	cd $(DIR_GC)
+	make DMD=$(DMD) -fwin32.mak $@
+	cd ..\..
+	$(DMD) -lib -of$(LIBDIR)\$@\$(LIBBASENAME) \
+		$(LIBDIR)\$@\druntime_core.lib \
+		$(LIBDIR)\$@\druntime_rt_dmd.lib \
+		$(LIBDIR)\$@\druntime_gc_basic.lib
+
+$(LIBDIR)\$(LIBBASENAME) : $(LIBDIR)\release\$(LIBBASENAME)
+	copy /y $** $@
+
+doc : $(ALL_DOCS)
+	cd $(DIR_CC)
+	make DMD=$(DMD) -fwin32.mak $@
+	cd ..
+#	cd $(DIR_RT)
+#	make DMD=$(DMD) -fwin32.mak $@
+#	cd ..\..
+#	cd $(DIR_GC)
+#	make DMD=$(DMD) -fwin32.mak $@
+#	cd ..\..
+
+######################################################
+
+clean : $(ALL_DOCS)
+	cd $(DIR_CC)
+	make DMD=$(DMD) -fwin32.mak $@
+	cd ..
+	cd $(DIR_RT)
+	make DMD=$(DMD) -fwin32.mak $@
+	cd ..\..
+	cd $(DIR_GC)
+	make DMD=$(DMD) -fwin32.mak $@
+	cd ..\..
+#find . -name "*.di" | xargs $(RM)
+#rm -rf $(LIBDIR) $(DOCDIR)
+
+# install :
+# 	make -C $(DIR_CC) --no-print-directory -fposix.mak install
+# 	make -C $(DIR_RT) --no-print-directory -fposix.mak install
+# 	make -C $(DIR_GC) --no-print-directory -fposix.mak install
+# 	$(CP) $(LIB_MASK) $(LIB_DEST)\.
+# 	$(CP) $(DUP_MASK) $(LIB_DEST)\.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/dmd.conf	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,2 @@
+[Environment]
+DFLAGS="-I%HOME%/common" "-I%HOME%/../import"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/gc/basic/gc.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,315 @@
+/**
+ * Contains the external GC interface.
+ *
+ * Copyright: Copyright Digital Mars 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module gc.gc;
+
+private
+{
+    import gc.gcx;
+    import gc.gcstats;
+    import core.stdc.stdlib;
+
+    version = GCCLASS;
+
+    version( GCCLASS )
+        alias GC gc_t;
+    else
+        alias GC* gc_t;
+
+    __gshared gc_t _gc;
+
+    extern (C) void thread_init();
+
+    struct Proxy
+    {
+        extern (C) void function() gc_enable;
+        extern (C) void function() gc_disable;
+        extern (C) void function() gc_collect;
+        extern (C) void function() gc_minimize;
+
+        extern (C) uint function(void*) gc_getAttr;
+        extern (C) uint function(void*, uint) gc_setAttr;
+        extern (C) uint function(void*, uint) gc_clrAttr;
+
+        extern (C) void*  function(size_t, uint) gc_malloc;
+        extern (C) void*  function(size_t, uint) gc_calloc;
+        extern (C) void*  function(void*, size_t, uint ba) gc_realloc;
+        extern (C) size_t function(void*, size_t, size_t) gc_extend;
+        extern (C) size_t function(size_t) gc_reserve;
+        extern (C) void   function(void*) gc_free;
+
+        extern (C) void*   function(void*) gc_addrOf;
+        extern (C) size_t  function(void*) gc_sizeOf;
+
+        extern (C) BlkInfo function(void*) gc_query;
+
+        extern (C) void function(void*) gc_addRoot;
+        extern (C) void function(void*, size_t) gc_addRange;
+
+        extern (C) void function(void*) gc_removeRoot;
+        extern (C) void function(void*) gc_removeRange;
+    }
+
+    __gshared Proxy  pthis;
+    __gshared Proxy* proxy;
+
+    void initProxy()
+    {
+        pthis.gc_enable = &gc_enable;
+        pthis.gc_disable = &gc_disable;
+        pthis.gc_collect = &gc_collect;
+        pthis.gc_minimize = &gc_minimize;
+
+        pthis.gc_getAttr = &gc_getAttr;
+        pthis.gc_setAttr = &gc_setAttr;
+        pthis.gc_clrAttr = &gc_clrAttr;
+
+        pthis.gc_malloc = &gc_malloc;
+        pthis.gc_calloc = &gc_calloc;
+        pthis.gc_realloc = &gc_realloc;
+        pthis.gc_extend = &gc_extend;
+        pthis.gc_reserve = &gc_reserve;
+        pthis.gc_free = &gc_free;
+
+        pthis.gc_addrOf = &gc_addrOf;
+        pthis.gc_sizeOf = &gc_sizeOf;
+
+        pthis.gc_query = &gc_query;
+
+        pthis.gc_addRoot = &gc_addRoot;
+        pthis.gc_addRange = &gc_addRange;
+
+        pthis.gc_removeRoot = &gc_removeRoot;
+        pthis.gc_removeRange = &gc_removeRange;
+    }
+}
+
+extern (C) void gc_init()
+{
+    version (GCCLASS)
+    {   void* p;
+        ClassInfo ci = GC.classinfo;
+
+        p = malloc(ci.init.length);
+        (cast(byte*)p)[0 .. ci.init.length] = ci.init[];
+        _gc = cast(GC)p;
+    }
+    else
+    {
+        _gc = cast(GC*) calloc(1, GC.sizeof);
+    }
+    _gc.initialize();
+    // NOTE: The GC must initialize the thread library
+    //       before its first collection.
+    thread_init();
+    initProxy();
+}
+
+extern (C) void gc_term()
+{
+    // NOTE: There may be daemons threads still running when this routine is
+    //       called.  If so, cleaning memory out from under then is a good
+    //       way to make them crash horribly.  This probably doesn't matter
+    //       much since the app is supposed to be shutting down anyway, but
+    //       I'm disabling cleanup for now until I can think about it some
+    //       more.
+    //
+    // NOTE: Due to popular demand, this has been re-enabled.  It still has
+    //       the problems mentioned above though, so I guess we'll see.
+    _gc.fullCollectNoStack(); // not really a 'collect all' -- still scans
+                              // static data area, roots, and ranges.
+    _gc.Dtor();
+}
+
+extern (C) void gc_enable()
+{
+    if( proxy is null )
+        return _gc.enable();
+    return proxy.gc_enable();
+}
+
+extern (C) void gc_disable()
+{
+    if( proxy is null )
+        return _gc.disable();
+    return proxy.gc_disable();
+}
+
+extern (C) void gc_collect()
+{
+    if( proxy is null )
+        return _gc.fullCollect();
+    return proxy.gc_collect();
+}
+
+
+extern (C) void gc_minimize()
+{
+    if( proxy is null )
+        return _gc.minimize();
+    return proxy.gc_minimize();
+}
+
+extern (C) uint gc_getAttr( void* p )
+{
+    if( proxy is null )
+        return _gc.getAttr( p );
+    return proxy.gc_getAttr( p );
+}
+
+extern (C) uint gc_setAttr( void* p, uint a )
+{
+    if( proxy is null )
+        return _gc.setAttr( p, a );
+    return proxy.gc_setAttr( p, a );
+}
+
+extern (C) uint gc_clrAttr( void* p, uint a )
+{
+    if( proxy is null )
+        return _gc.clrAttr( p, a );
+    return proxy.gc_clrAttr( p, a );
+}
+
+extern (C) void* gc_malloc( size_t sz, uint ba = 0 )
+{
+    if( proxy is null )
+        return _gc.malloc( sz, ba );
+    return proxy.gc_malloc( sz, ba );
+}
+
+extern (C) void* gc_calloc( size_t sz, uint ba = 0 )
+{
+    if( proxy is null )
+        return _gc.calloc( sz, ba );
+    return proxy.gc_calloc( sz, ba );
+}
+
+extern (C) void* gc_realloc( void* p, size_t sz, uint ba = 0 )
+{
+    if( proxy is null )
+        return _gc.realloc( p, sz, ba );
+    return proxy.gc_realloc( p, sz, ba );
+}
+
+extern (C) size_t gc_extend( void* p, size_t mx, size_t sz )
+{
+    if( proxy is null )
+        return _gc.extend( p, mx, sz );
+    return proxy.gc_extend( p, mx, sz );
+}
+
+extern (C) size_t gc_reserve( size_t sz )
+{
+    if( proxy is null )
+        return _gc.reserve( sz );
+    return proxy.gc_reserve( sz );
+}
+
+extern (C) void gc_free( void* p )
+{
+    if( proxy is null )
+        return _gc.free( p );
+    return proxy.gc_free( p );
+}
+
+extern (C) void* gc_addrOf( void* p )
+{
+    if( proxy is null )
+        return _gc.addrOf( p );
+    return proxy.gc_addrOf( p );
+}
+
+extern (C) size_t gc_sizeOf( void* p )
+{
+    if( proxy is null )
+        return _gc.sizeOf( p );
+    return proxy.gc_sizeOf( p );
+}
+
+extern (C) BlkInfo gc_query( void* p )
+{
+    if( proxy is null )
+        return _gc.query( p );
+    return proxy.gc_query( p );
+}
+
+// NOTE: This routine is experimental.  The stats or function name may change
+//       before it is made officially available.
+extern (C) GCStats gc_stats()
+{
+    if( proxy is null )
+    {
+        GCStats stats = void;
+        _gc.getStats( stats );
+        return stats;
+    }
+    // TODO: Add proxy support for this once the layout of GCStats is
+    //       finalized.
+    //return proxy.gc_stats();
+    return GCStats.init;
+}
+
+extern (C) void gc_addRoot( void* p )
+{
+    if( proxy is null )
+        return _gc.addRoot( p );
+    return proxy.gc_addRoot( p );
+}
+
+extern (C) void gc_addRange( void* p, size_t sz )
+{
+    if( proxy is null )
+        return _gc.addRange( p, sz );
+    return proxy.gc_addRange( p, sz );
+}
+
+extern (C) void gc_removeRoot( void* p )
+{
+    if( proxy is null )
+        return _gc.removeRoot( p );
+    return proxy.gc_removeRoot( p );
+}
+
+extern (C) void gc_removeRange( void* p )
+{
+    if( proxy is null )
+        return _gc.removeRange( p );
+    return proxy.gc_removeRange( p );
+}
+
+extern (C) Proxy* gc_getProxy()
+{
+    return &pthis;
+}
+
+export extern (C) void gc_setProxy( Proxy* p )
+{
+    if( proxy !is null )
+    {
+        // TODO: Decide if this is an error condition.
+    }
+    proxy = p;
+    foreach( r; _gc.rootIter )
+        proxy.gc_addRoot( r );
+    foreach( r; _gc.rangeIter )
+        proxy.gc_addRange( r.pbot, r.ptop - r.pbot );
+}
+
+export extern (C) void gc_clrProxy()
+{
+    foreach( r; _gc.rangeIter )
+        proxy.gc_removeRange( r.pbot );
+    foreach( r; _gc.rootIter )
+        proxy.gc_removeRoot( r );
+    proxy = null;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/gc/basic/gcalloc.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,201 @@
+/**
+ * Contains OS-level allocation routines.
+ *
+ * Copyright: Copyright Digital Mars 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, David Friedman, Sean Kelly
+ *
+ *          Copyright Digital Mars 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module gc.gcalloc;
+
+
+version (Windows)
+{
+    private import core.sys.windows.windows;
+
+    alias int pthread_t;
+
+    pthread_t pthread_self()
+    {
+        return cast(pthread_t) GetCurrentThreadId();
+    }
+
+    //version = GC_Use_Alloc_Win32;
+}
+else version (Posix)
+{
+    private import core.sys.posix.sys.mman;
+    private import core.stdc.stdlib;
+
+    //version = GC_Use_Alloc_MMap;
+}
+else
+{
+    private import core.stdc.stdlib;
+
+    //version = GC_Use_Alloc_Malloc;
+}
+
+/+
+static if(is(typeof(VirtualAlloc)))
+    version = GC_Use_Alloc_Win32;
+else static if (is(typeof(mmap)))
+    version = GC_Use_Alloc_MMap;
+else static if (is(typeof(valloc)))
+    version = GC_Use_Alloc_Valloc;
+else static if (is(typeof(malloc)))
+    version = GC_Use_Alloc_Malloc;
+else static assert(false, "No supported allocation methods available.");
++/
+
+static if (is(typeof(VirtualAlloc))) // version (GC_Use_Alloc_Win32)
+{
+    /**
+     * Map memory.
+     */
+    void *os_mem_map(size_t nbytes)
+    {
+        return VirtualAlloc(null, nbytes, MEM_RESERVE, PAGE_READWRITE);
+    }
+
+
+    /**
+     * Commit memory.
+     * Returns:
+     *      0       success
+     *      !=0     failure
+     */
+    int os_mem_commit(void *base, size_t offset, size_t nbytes)
+    {   void *p;
+
+        p = VirtualAlloc(base + offset, nbytes, MEM_COMMIT, PAGE_READWRITE);
+    return cast(int)(p is null);
+    }
+
+
+    /**
+     * Decommit memory.
+     * Returns:
+     *      0       success
+     *      !=0     failure
+     */
+    int os_mem_decommit(void *base, size_t offset, size_t nbytes)
+    {
+    return cast(int)(VirtualFree(base + offset, nbytes, MEM_DECOMMIT) == 0);
+    }
+
+
+    /**
+     * Unmap memory allocated with os_mem_map().
+     * Memory must have already been decommitted.
+     * Returns:
+     *      0       success
+     *      !=0     failure
+     */
+    int os_mem_unmap(void *base, size_t nbytes)
+    {
+        return cast(int)(VirtualFree(base, 0, MEM_RELEASE) == 0);
+    }
+}
+else static if (is(typeof(mmap)))  // else version (GC_Use_Alloc_MMap)
+{
+    void *os_mem_map(size_t nbytes)
+    {   void *p;
+
+        p = mmap(null, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+        return (p == MAP_FAILED) ? null : p;
+    }
+
+
+    int os_mem_commit(void *base, size_t offset, size_t nbytes)
+    {
+        return 0;
+    }
+
+
+    int os_mem_decommit(void *base, size_t offset, size_t nbytes)
+    {
+        return 0;
+    }
+
+
+    int os_mem_unmap(void *base, size_t nbytes)
+    {
+        return munmap(base, nbytes);
+    }
+}
+else static if (is(typeof(valloc))) // else version (GC_Use_Alloc_Valloc)
+{
+    void *os_mem_map(size_t nbytes)
+    {
+        return valloc(nbytes);
+    }
+
+
+    int os_mem_commit(void *base, size_t offset, size_t nbytes)
+    {
+        return 0;
+    }
+
+
+    int os_mem_decommit(void *base, size_t offset, size_t nbytes)
+    {
+        return 0;
+    }
+
+
+    int os_mem_unmap(void *base, size_t nbytes)
+    {
+        free(base);
+        return 0;
+    }
+}
+else static if (is(typeof(malloc))) // else version (GC_Use_Alloc_Malloc)
+{
+    // NOTE: This assumes malloc granularity is at least (void*).sizeof.  If
+    //       (req_size + PAGESIZE) is allocated, and the pointer is rounded up
+    //       to PAGESIZE alignment, there will be space for a void* at the end
+    //       after PAGESIZE bytes used by the GC.
+
+
+    private import gcx : PAGESIZE;
+
+
+    const size_t PAGE_MASK = PAGESIZE - 1;
+
+
+    void *os_mem_map(size_t nbytes)
+    {   byte *p, q;
+        p = cast(byte *) malloc(nbytes + PAGESIZE);
+        q = p + ((PAGESIZE - ((cast(size_t) p & PAGE_MASK))) & PAGE_MASK);
+        * cast(void**)(q + nbytes) = p;
+        return q;
+    }
+
+
+    int os_mem_commit(void *base, size_t offset, size_t nbytes)
+    {
+        return 0;
+    }
+
+
+    int os_mem_decommit(void *base, size_t offset, size_t nbytes)
+    {
+        return 0;
+    }
+
+
+    int os_mem_unmap(void *base, size_t nbytes)
+    {
+        free( *cast(void**)( cast(byte*) base + nbytes ) );
+        return 0;
+    }
+}
+else
+{
+    static assert(false, "No supported allocation methods available.");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/gc/basic/gcbits.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,193 @@
+/**
+ * Contains a bitfield used by the GC.
+ *
+ * Copyright: Copyright Digital Mars 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, David Friedman, Sean Kelly
+ *
+ *          Copyright Digital Mars 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module gc.gcbits;
+
+
+private
+{
+    import core.bitop;
+    import core.stdc.string;
+    import core.stdc.stdlib;
+    extern (C) void onOutOfMemoryError();
+}
+
+
+version (DigitalMars)
+{
+    version = bitops;
+}
+else version (GNU)
+{
+    // use the unoptimized version
+}
+else version (D_InlineAsm_X86)
+{
+    version = Asm86;
+}
+
+struct GCBits
+{
+    const int BITS_PER_WORD = 32;
+    const int BITS_SHIFT = 5;
+    const int BITS_MASK = 31;
+
+    uint*  data = null;
+    size_t nwords = 0;    // allocated words in data[] excluding sentinals
+    size_t nbits = 0;     // number of bits in data[] excluding sentinals
+
+    void Dtor()
+    {
+        if (data)
+        {
+            free(data);
+            data = null;
+        }
+    }
+
+    invariant()
+    {
+        if (data)
+        {
+            assert(nwords * data[0].sizeof * 8 >= nbits);
+        }
+    }
+
+    void alloc(size_t nbits)
+    {
+        this.nbits = nbits;
+        nwords = (nbits + (BITS_PER_WORD - 1)) >> BITS_SHIFT;
+        data = cast(uint*)calloc(nwords + 2, uint.sizeof);
+        if (!data)
+            onOutOfMemoryError();
+    }
+
+    uint test(size_t i)
+    in
+    {
+        assert(i < nbits);
+    }
+    body
+    {
+        //return (cast(bit *)(data + 1))[i];
+        return data[1 + (i >> BITS_SHIFT)] & (1 << (i & BITS_MASK));
+    }
+
+    void set(size_t i)
+    in
+    {
+        assert(i < nbits);
+    }
+    body
+    {
+        //(cast(bit *)(data + 1))[i] = 1;
+        data[1 + (i >> BITS_SHIFT)] |= (1 << (i & BITS_MASK));
+    }
+
+    void clear(size_t i)
+    in
+    {
+        assert(i < nbits);
+    }
+    body
+    {
+        //(cast(bit *)(data + 1))[i] = 0;
+        data[1 + (i >> BITS_SHIFT)] &= ~(1 << (i & BITS_MASK));
+    }
+
+    uint testClear(size_t i)
+    {
+        version (bitops)
+        {
+            return std.intrinsic.btr(data + 1, i);
+        }
+        else version (Asm86)
+        {
+            asm
+            {
+                naked                   ;
+                mov     EAX,data[EAX]   ;
+                mov     ECX,i-4[ESP]    ;
+                btr     4[EAX],ECX      ;
+                sbb     EAX,EAX         ;
+                ret     4               ;
+            }
+        }
+        else
+        {   uint result;
+
+            //result = (cast(bit *)(data + 1))[i];
+            //(cast(bit *)(data + 1))[i] = 0;
+
+            uint* p = &data[1 + (i >> BITS_SHIFT)];
+            uint  mask = (1 << (i & BITS_MASK));
+            result = *p & mask;
+            *p &= ~mask;
+            return result;
+        }
+    }
+
+    void zero()
+    {
+        memset(data + 1, 0, nwords * uint.sizeof);
+    }
+
+    void copy(GCBits *f)
+    in
+    {
+        assert(nwords == f.nwords);
+    }
+    body
+    {
+        memcpy(data + 1, f.data + 1, nwords * uint.sizeof);
+    }
+
+    uint* base()
+    in
+    {
+        assert(data);
+    }
+    body
+    {
+        return data + 1;
+    }
+}
+
+unittest
+{
+    GCBits b;
+
+    b.alloc(786);
+    assert(b.test(123) == 0);
+    assert(b.testClear(123) == 0);
+    b.set(123);
+    assert(b.test(123) != 0);
+    assert(b.testClear(123) != 0);
+    assert(b.test(123) == 0);
+
+    b.set(785);
+    b.set(0);
+    assert(b.test(785) != 0);
+    assert(b.test(0) != 0);
+    b.zero();
+    assert(b.test(785) == 0);
+    assert(b.test(0) == 0);
+
+    GCBits b2;
+    b2.alloc(786);
+    b2.set(38);
+    b.copy(&b2);
+    assert(b.test(38) != 0);
+    b2.Dtor();
+
+    b.Dtor();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/gc/basic/gcstats.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,26 @@
+/**
+ * Contains a struct for storing GC statistics.
+ *
+ * Copyright: Copyright Digital Mars 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, Sean Kelly
+ *
+ *          Copyright Digital Mars 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module gc.gcstats;
+
+
+/**
+ *
+ */
+struct GCStats
+{
+    size_t poolsize;        // total size of pool
+    size_t usedsize;        // bytes allocated
+    size_t freeblocks;      // number of blocks marked FREE
+    size_t freelistsize;    // total of memory on free lists
+    size_t pageblocks;      // number of blocks marked PAGE
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/gc/basic/gcx.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,3010 @@
+/**
+ * Contains the garbage collector implementation.
+ *
+ * Copyright: Copyright Digital Mars 2001 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Walter Bright, David Friedman, Sean Kelly
+ *
+ *          Copyright Digital Mars 2001 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module gc.gcx;
+
+// D Programming Language Garbage Collector implementation
+
+/************** Debugging ***************************/
+
+//debug = PRINTF;               // turn on printf's
+//debug = COLLECT_PRINTF;       // turn on printf's
+//debug = THREADINVARIANT;      // check thread integrity
+//debug = LOGGING;              // log allocations / frees
+//debug = MEMSTOMP;             // stomp on memory
+//debug = SENTINEL;             // add underrun/overrrun protection
+//debug = PTRCHECK;             // more pointer checking
+//debug = PTRCHECK2;            // thorough but slow pointer checking
+
+/*************** Configuration *********************/
+
+version = STACKGROWSDOWN;       // growing the stack means subtracting from the stack pointer
+                                // (use for Intel X86 CPUs)
+                                // else growing the stack means adding to the stack pointer
+version = MULTI_THREADED;       // produce multithreaded version
+
+/***************************************************/
+
+private import gc.gcbits;
+private import gc.gcstats;
+private import gc.gcalloc;
+
+private import cstdlib = core.stdc.stdlib : calloc, free, malloc, realloc;
+private import core.stdc.string;
+
+debug (PRINTF) import core.stdc.stdio : printf;
+debug (COLLECT_PRINTF) import core.stdc.stdio : printf;
+debug private import core.stdc.stdio;
+
+private
+{
+    enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001,
+        NO_SCAN  = 0b0000_0010,
+        NO_MOVE  = 0b0000_0100,
+        ALL_BITS = 0b1111_1111
+    }
+
+    struct BlkInfo
+    {
+        void*  base;
+        size_t size;
+        uint   attr;
+    }
+
+    extern (C) void* rt_stackBottom();
+    extern (C) void* rt_stackTop();
+
+    extern (C) void rt_finalize( void* p, bool det = true );
+
+    version (MULTI_THREADED)
+    {
+        extern (C) bool thread_needLock();
+        extern (C) void thread_suspendAll();
+        extern (C) void thread_resumeAll();
+
+        alias void delegate( void*, void* ) scanFn;
+        extern (C) void thread_scanAll( scanFn fn, void* curStackTop = null );
+    }
+
+    extern (C) void onOutOfMemoryError();
+
+    enum
+    {
+        OPFAIL = ~cast(size_t)0
+    }
+}
+
+
+alias GC gc_t;
+
+
+/* ======================= Leak Detector =========================== */
+
+
+debug (LOGGING)
+{
+    struct Log
+    {
+        void*  p;
+        size_t size;
+        size_t line;
+        char*  file;
+        void*  parent;
+
+        void print()
+        {
+            printf("    p = %x, size = %d, parent = %x ", p, size, parent);
+            if (file)
+            {
+                printf("%s(%u)", file, line);
+            }
+            printf("\n");
+        }
+    }
+
+
+    struct LogArray
+    {
+        size_t dim;
+        size_t allocdim;
+        Log *data;
+
+        void Dtor()
+        {
+            if (data)
+                cstdlib.free(data);
+            data = null;
+        }
+
+        void reserve(size_t nentries)
+        {
+            assert(dim <= allocdim);
+            if (allocdim - dim < nentries)
+            {
+                allocdim = (dim + nentries) * 2;
+                assert(dim + nentries <= allocdim);
+                if (!data)
+                {
+                    data = cast(Log*)cstdlib.malloc(allocdim * Log.sizeof);
+                    if (!data && allocdim)
+                        onOutOfMemoryError();
+                }
+                else
+                {   Log *newdata;
+
+                    newdata = cast(Log*)cstdlib.malloc(allocdim * Log.sizeof);
+                    if (!newdata && allocdim)
+                        onOutOfMemoryError();
+                    memcpy(newdata, data, dim * Log.sizeof);
+                    cstdlib.free(data);
+                    data = newdata;
+                }
+            }
+        }
+
+
+        void push(Log log)
+        {
+            reserve(1);
+            data[dim++] = log;
+        }
+
+        void remove(size_t i)
+        {
+            memmove(data + i, data + i + 1, (dim - i) * Log.sizeof);
+            dim--;
+        }
+
+
+        size_t find(void *p)
+        {
+            for (size_t i = 0; i < dim; i++)
+            {
+                if (data[i].p == p)
+                    return i;
+            }
+            return OPFAIL; // not found
+        }
+
+
+        void copy(LogArray *from)
+        {
+            reserve(from.dim - dim);
+            assert(from.dim <= allocdim);
+            memcpy(data, from.data, from.dim * Log.sizeof);
+            dim = from.dim;
+        }
+    }
+}
+
+
+/* ============================ GC =============================== */
+
+
+class GCLock { }                // just a dummy so we can get a global lock
+
+
+const uint GCVERSION = 1;       // increment every time we change interface
+                                // to GC.
+
+class GC
+{
+    // For passing to debug code (not thread safe)
+    __gshared size_t line;
+    __gshared char*  file;
+
+    uint gcversion = GCVERSION;
+
+    Gcx *gcx;                   // implementation
+    __gshared ClassInfo gcLock;    // global lock
+
+
+    void initialize()
+    {
+        gcLock = GCLock.classinfo;
+        gcx = cast(Gcx*)cstdlib.calloc(1, Gcx.sizeof);
+        if (!gcx)
+            onOutOfMemoryError();
+        gcx.initialize();
+        setStackBottom(rt_stackBottom());
+    }
+
+
+    void Dtor()
+    {
+        version (linux)
+        {
+            //debug(PRINTF) printf("Thread %x ", pthread_self());
+            //debug(PRINTF) printf("GC.Dtor()\n");
+        }
+
+        if (gcx)
+        {
+            gcx.Dtor();
+            cstdlib.free(gcx);
+            gcx = null;
+        }
+    }
+
+
+    invariant()
+    {
+        if (gcx)
+        {
+            gcx.thread_Invariant();
+        }
+    }
+
+
+    /**
+     *
+     */
+    void enable()
+    {
+        if (!thread_needLock())
+        {
+            assert(gcx.disabled > 0);
+            gcx.disabled--;
+        }
+        else synchronized (gcLock)
+        {
+            assert(gcx.disabled > 0);
+            gcx.disabled--;
+        }
+    }
+
+
+    /**
+     *
+     */
+    void disable()
+    {
+        if (!thread_needLock())
+        {
+            gcx.disabled++;
+        }
+        else synchronized (gcLock)
+        {
+            gcx.disabled++;
+        }
+    }
+
+
+    /**
+     *
+     */
+    uint getAttr(void* p)
+    {
+        if (!p)
+        {
+            return 0;
+        }
+
+        uint go()
+        {
+            Pool* pool = gcx.findPool(p);
+            uint  oldb = 0;
+
+            if (pool)
+            {
+                auto biti = cast(size_t)(p - pool.baseAddr) / 16;
+
+                oldb = gcx.getBits(pool, biti);
+            }
+            return oldb;
+        }
+
+        if (!thread_needLock())
+        {
+            return go();
+        }
+        else synchronized (gcLock)
+        {
+            return go();
+        }
+    }
+
+
+    /**
+     *
+     */
+    uint setAttr(void* p, uint mask)
+    {
+        if (!p)
+        {
+            return 0;
+        }
+
+        uint go()
+        {
+            Pool* pool = gcx.findPool(p);
+            uint  oldb = 0;
+
+            if (pool)
+            {
+                auto biti = cast(size_t)(p - pool.baseAddr) / 16;
+
+                oldb = gcx.getBits(pool, biti);
+                gcx.setBits(pool, biti, mask);
+            }
+            return oldb;
+        }
+
+        if (!thread_needLock())
+        {
+            return go();
+        }
+        else synchronized (gcLock)
+        {
+            return go();
+        }
+    }
+
+
+    /**
+     *
+     */
+    uint clrAttr(void* p, uint mask)
+    {
+        if (!p)
+        {
+            return 0;
+        }
+
+        uint go()
+        {
+            Pool* pool = gcx.findPool(p);
+            uint  oldb = 0;
+
+            if (pool)
+            {
+                auto biti = cast(size_t)(p - pool.baseAddr) / 16;
+
+                oldb = gcx.getBits(pool, biti);
+                gcx.clrBits(pool, biti, mask);
+            }
+            return oldb;
+        }
+
+        if (!thread_needLock())
+        {
+            return go();
+        }
+        else synchronized (gcLock)
+        {
+            return go();
+        }
+    }
+
+
+    /**
+     *
+     */
+    void *malloc(size_t size, uint bits = 0)
+    {
+        if (!size)
+        {
+            return null;
+        }
+
+        // Since a finalizer could launch a new thread, we always need to lock
+        // when collecting.  The safest way to do this is to simply always lock
+        // when allocating.
+        synchronized (gcLock)
+        {
+            return mallocNoSync(size, bits);
+        }
+    }
+
+
+    //
+    //
+    //
+    private void *mallocNoSync(size_t size, uint bits = 0)
+    {
+        assert(size != 0);
+
+        void *p = null;
+        Bins bin;
+
+        //debug(PRINTF) printf("GC::malloc(size = %d, gcx = %p)\n", size, gcx);
+        assert(gcx);
+        //debug(PRINTF) printf("gcx.self = %x, pthread_self() = %x\n", gcx.self, pthread_self());
+
+        size += SENTINEL_EXTRA;
+
+        // Compute size bin
+        // Cache previous binsize lookup - Dave Fladebo.
+        __gshared size_t lastsize = -1;
+        __gshared Bins lastbin;
+        if (size == lastsize)
+            bin = lastbin;
+        else
+        {
+            bin = gcx.findBin(size);
+            lastsize = size;
+            lastbin = bin;
+        }
+
+        if (bin < B_PAGE)
+        {
+            int  state     = gcx.disabled ? 1 : 0;
+            bool collected = false;
+
+            while (!gcx.bucket[bin] && !gcx.allocPage(bin))
+            {
+                switch (state)
+                {
+                case 0:
+                    gcx.fullcollectshell();
+                    collected = true;
+                    state = 1;
+                    continue;
+                case 1:
+                    gcx.newPool(1);
+                    state = 2;
+                    continue;
+                case 2:
+                    if (collected)
+                        onOutOfMemoryError();
+                    state = 0;
+                    continue;
+                default:
+                    assert(false);
+                }
+            }
+            p = gcx.bucket[bin];
+
+            // Return next item from free list
+            gcx.bucket[bin] = (cast(List*)p).next;
+            if( !(bits & BlkAttr.NO_SCAN) )
+                memset(p + size, 0, binsize[bin] - size);
+            //debug(PRINTF) printf("\tmalloc => %x\n", p);
+            debug (MEMSTOMP) memset(p, 0xF0, size);
+        }
+        else
+        {
+            p = gcx.bigAlloc(size);
+            if (!p)
+                onOutOfMemoryError();
+        }
+        size -= SENTINEL_EXTRA;
+        p = sentinel_add(p);
+        sentinel_init(p, size);
+        gcx.log_malloc(p, size);
+
+        if (bits)
+        {
+            Pool *pool = gcx.findPool(p);
+            assert(pool);
+
+            gcx.setBits(pool, cast(size_t)(p - pool.baseAddr) / 16, bits);
+        }
+        return p;
+    }
+
+
+    /**
+     *
+     */
+    void *calloc(size_t size, uint bits = 0)
+    {
+        if (!size)
+        {
+            return null;
+        }
+
+        // Since a finalizer could launch a new thread, we always need to lock
+        // when collecting.  The safest way to do this is to simply always lock
+        // when allocating.
+        synchronized (gcLock)
+        {
+            return callocNoSync(size, bits);
+        }
+    }
+
+
+    //
+    //
+    //
+    private void *callocNoSync(size_t size, uint bits = 0)
+    {
+        assert(size != 0);
+
+        //debug(PRINTF) printf("calloc: %x len %d\n", p, len);
+        void *p = mallocNoSync(size, bits);
+        memset(p, 0, size);
+        return p;
+    }
+
+
+    /**
+     *
+     */
+    void *realloc(void *p, size_t size, uint bits = 0)
+    {
+        // Since a finalizer could launch a new thread, we always need to lock
+        // when collecting.  The safest way to do this is to simply always lock
+        // when allocating.
+        synchronized (gcLock)
+        {
+            return reallocNoSync(p, size, bits);
+        }
+    }
+
+
+    //
+    //
+    //
+    private void *reallocNoSync(void *p, size_t size, uint bits = 0)
+    {
+        if (!size)
+        {   if (p)
+            {   freeNoSync(p);
+                p = null;
+            }
+        }
+        else if (!p)
+        {
+            p = mallocNoSync(size, bits);
+        }
+        else
+        {   void *p2;
+            size_t psize;
+
+            //debug(PRINTF) printf("GC::realloc(p = %x, size = %u)\n", p, size);
+            version (SENTINEL)
+            {
+                sentinel_Invariant(p);
+                psize = *sentinel_size(p);
+                if (psize != size)
+                {
+                    if (psize)
+                    {
+                        Pool *pool = gcx.findPool(p);
+
+                        if (pool)
+                        {
+                            auto biti = cast(size_t)(p - pool.baseAddr) / 16;
+
+                            if (bits)
+                            {
+                                gcx.clrBits(pool, biti, BlkAttr.ALL_BITS);
+                                gcx.setBits(pool, biti, bits);
+                            }
+                            else
+                            {
+                                bits = gcx.getBits(pool, biti);
+                            }
+                        }
+                    }
+                    p2 = mallocNoSync(size, bits);
+                    if (psize < size)
+                        size = psize;
+                    //debug(PRINTF) printf("\tcopying %d bytes\n",size);
+                    memcpy(p2, p, size);
+                    p = p2;
+                }
+            }
+            else
+            {
+                psize = gcx.findSize(p);        // find allocated size
+                if (psize >= PAGESIZE && size >= PAGESIZE)
+                {
+                    auto psz = psize / PAGESIZE;
+                    auto newsz = (size + PAGESIZE - 1) / PAGESIZE;
+                    if (newsz == psz)
+                        return p;
+
+                    auto pool = gcx.findPool(p);
+                    auto pagenum = (p - pool.baseAddr) / PAGESIZE;
+
+                    if (newsz < psz)
+                    {   // Shrink in place
+                        synchronized (gcLock)
+                        {
+                            debug (MEMSTOMP) memset(p + size, 0xF2, psize - size);
+                            pool.freePages(pagenum + newsz, psz - newsz);
+                        }
+                        return p;
+                    }
+                    else if (pagenum + newsz <= pool.npages)
+                    {
+                        // Attempt to expand in place
+                        synchronized (gcLock)
+                        {
+                            for (size_t i = pagenum + psz; 1;)
+                            {
+                                if (i == pagenum + newsz)
+                                {
+                                    debug (MEMSTOMP) memset(p + psize, 0xF0, size - psize);
+                                    memset(&pool.pagetable[pagenum + psz], B_PAGEPLUS, newsz - psz);
+                                    return p;
+                                }
+                                if (i == pool.ncommitted)
+                                {
+                                    auto u = pool.extendPages(pagenum + newsz - pool.ncommitted);
+                                    if (u == OPFAIL)
+                                        break;
+                                    i = pagenum + newsz;
+                                    continue;
+                                }
+                                if (pool.pagetable[i] != B_FREE)
+                                    break;
+                                i++;
+                            }
+                        }
+                    }
+                }
+                if (psize < size ||             // if new size is bigger
+                    psize > size * 2)           // or less than half
+                {
+                    if (psize)
+                    {
+                        Pool *pool = gcx.findPool(p);
+
+                        if (pool)
+                        {
+                            auto biti = cast(size_t)(p - pool.baseAddr) / 16;
+
+                            if (bits)
+                            {
+                                gcx.clrBits(pool, biti, BlkAttr.ALL_BITS);
+                                gcx.setBits(pool, biti, bits);
+                            }
+                            else
+                            {
+                                bits = gcx.getBits(pool, biti);
+                            }
+                        }
+                    }
+                    p2 = mallocNoSync(size, bits);
+                    if (psize < size)
+                        size = psize;
+                    //debug(PRINTF) printf("\tcopying %d bytes\n",size);
+                    memcpy(p2, p, size);
+                    p = p2;
+                }
+            }
+        }
+        return p;
+    }
+
+
+    /**
+     * Attempt to in-place enlarge the memory block pointed to by p by at least
+     * minbytes beyond its current capacity, up to a maximum of maxsize.  This
+     * does not attempt to move the memory block (like realloc() does).
+     *
+     * Returns:
+     *  0 if could not extend p,
+     *  total size of entire memory block if successful.
+     */
+    size_t extend(void* p, size_t minsize, size_t maxsize)
+    {
+        if (!thread_needLock())
+        {
+            return extendNoSync(p, minsize, maxsize);
+        }
+        else synchronized (gcLock)
+        {
+            return extendNoSync(p, minsize, maxsize);
+        }
+    }
+
+
+    //
+    //
+    //
+    private size_t extendNoSync(void* p, size_t minsize, size_t maxsize)
+    in
+    {
+        assert( minsize <= maxsize );
+    }
+    body
+    {
+        //debug(PRINTF) printf("GC::extend(p = %x, minsize = %u, maxsize = %u)\n", p, minsize, maxsize);
+        version (SENTINEL)
+        {
+            return 0;
+        }
+        auto psize = gcx.findSize(p);   // find allocated size
+        if (psize < PAGESIZE)
+            return 0;                   // cannot extend buckets
+
+        auto psz = psize / PAGESIZE;
+        auto minsz = (minsize + PAGESIZE - 1) / PAGESIZE;
+        auto maxsz = (maxsize + PAGESIZE - 1) / PAGESIZE;
+
+        auto pool = gcx.findPool(p);
+        auto pagenum = (p - pool.baseAddr) / PAGESIZE;
+
+        size_t sz;
+        for (sz = 0; sz < maxsz; sz++)
+        {
+            auto i = pagenum + psz + sz;
+            if (i == pool.ncommitted)
+                break;
+            if (pool.pagetable[i] != B_FREE)
+            {   if (sz < minsz)
+                    return 0;
+                break;
+            }
+        }
+        if (sz >= minsz)
+        {
+        }
+        else if (pagenum + psz + sz == pool.ncommitted)
+        {
+            auto u = pool.extendPages(minsz - sz);
+            if (u == OPFAIL)
+                return 0;
+            sz = minsz;
+        }
+        else
+            return 0;
+        debug (MEMSTOMP) memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize);
+        memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz);
+        gcx.p_cache = null;
+        gcx.size_cache = 0;
+        return (psz + sz) * PAGESIZE;
+    }
+
+
+    /**
+     *
+     */
+    size_t reserve(size_t size)
+    {
+        if (!size)
+        {
+            return 0;
+        }
+
+        if (!thread_needLock())
+        {
+            return reserveNoSync(size);
+        }
+        else synchronized (gcLock)
+        {
+            return reserveNoSync(size);
+        }
+    }
+
+
+    //
+    //
+    //
+    private size_t reserveNoSync(size_t size)
+    {
+        assert(size != 0);
+        assert(gcx);
+
+        return gcx.reserve(size);
+    }
+
+
+    /**
+     *
+     */
+    void free(void *p)
+    {
+        if (!p)
+        {
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+            return freeNoSync(p);
+        }
+        else synchronized (gcLock)
+        {
+            return freeNoSync(p);
+        }
+    }
+
+
+    //
+    //
+    //
+    private void freeNoSync(void *p)
+    {
+        assert (p);
+
+        Pool*  pool;
+        size_t pagenum;
+        Bins   bin;
+        size_t biti;
+
+        // Find which page it is in
+        pool = gcx.findPool(p);
+        if (!pool)                              // if not one of ours
+            return;                             // ignore
+        sentinel_Invariant(p);
+        p = sentinel_sub(p);
+        pagenum = cast(size_t)(p - pool.baseAddr) / PAGESIZE;
+        biti = cast(size_t)(p - pool.baseAddr) / 16;
+        gcx.clrBits(pool, biti, BlkAttr.ALL_BITS);
+
+        bin = cast(Bins)pool.pagetable[pagenum];
+        if (bin == B_PAGE)              // if large alloc
+        {   size_t npages;
+            size_t n;
+
+            // Free pages
+            npages = 1;
+            n = pagenum;
+            while (++n < pool.ncommitted && pool.pagetable[n] == B_PAGEPLUS)
+                npages++;
+            debug (MEMSTOMP) memset(p, 0xF2, npages * PAGESIZE);
+            pool.freePages(pagenum, npages);
+        }
+        else
+        {   // Add to free list
+            List *list = cast(List*)p;
+
+            debug (MEMSTOMP) memset(p, 0xF2, binsize[bin]);
+
+            list.next = gcx.bucket[bin];
+            gcx.bucket[bin] = list;
+        }
+        gcx.log_free(sentinel_add(p));
+    }
+
+
+    /**
+     * Determine the base address of the block containing p.  If p is not a gc
+     * allocated pointer, return null.
+     */
+    void* addrOf(void *p)
+    {
+        if (!p)
+        {
+            return null;
+        }
+
+        if (!thread_needLock())
+        {
+            return addrOfNoSync(p);
+        }
+        else synchronized (gcLock)
+        {
+            return addrOfNoSync(p);
+        }
+    }
+
+
+    //
+    //
+    //
+    void* addrOfNoSync(void *p)
+    {
+        if (!p)
+        {
+            return null;
+        }
+
+        return gcx.findBase(p);
+    }
+
+
+    /**
+     * Determine the allocated size of pointer p.  If p is an interior pointer
+     * or not a gc allocated pointer, return 0.
+     */
+    size_t sizeOf(void *p)
+    {
+        if (!p)
+        {
+            return 0;
+        }
+
+        if (!thread_needLock())
+        {
+            return sizeOfNoSync(p);
+        }
+        else synchronized (gcLock)
+        {
+            return sizeOfNoSync(p);
+        }
+    }
+
+
+    //
+    //
+    //
+    private size_t sizeOfNoSync(void *p)
+    {
+        assert (p);
+
+        version (SENTINEL)
+        {
+            p = sentinel_sub(p);
+            size_t size = gcx.findSize(p);
+
+            // Check for interior pointer
+            // This depends on:
+            // 1) size is a power of 2 for less than PAGESIZE values
+            // 2) base of memory pool is aligned on PAGESIZE boundary
+            if (cast(size_t)p & (size - 1) & (PAGESIZE - 1))
+                size = 0;
+            return size ? size - SENTINEL_EXTRA : 0;
+        }
+        else
+        {
+            if (p == gcx.p_cache)
+                return gcx.size_cache;
+
+            size_t size = gcx.findSize(p);
+
+            // Check for interior pointer
+            // This depends on:
+            // 1) size is a power of 2 for less than PAGESIZE values
+            // 2) base of memory pool is aligned on PAGESIZE boundary
+            if (cast(size_t)p & (size - 1) & (PAGESIZE - 1))
+                size = 0;
+            else
+            {
+                gcx.p_cache = p;
+                gcx.size_cache = size;
+            }
+
+            return size;
+        }
+    }
+
+
+    /**
+     * Determine the base address of the block containing p.  If p is not a gc
+     * allocated pointer, return null.
+     */
+    BlkInfo query(void *p)
+    {
+        if (!p)
+        {
+            BlkInfo i;
+            return  i;
+        }
+
+        if (!thread_needLock())
+        {
+            return queryNoSync(p);
+        }
+        else synchronized (gcLock)
+        {
+            return queryNoSync(p);
+        }
+    }
+
+
+    //
+    //
+    //
+    BlkInfo queryNoSync(void *p)
+    {
+        assert(p);
+
+        return gcx.getInfo(p);
+    }
+
+
+    /**
+     * Verify that pointer p:
+     *  1) belongs to this memory pool
+     *  2) points to the start of an allocated piece of memory
+     *  3) is not on a free list
+     */
+    void check(void *p)
+    {
+        if (!p)
+        {
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+            checkNoSync(p);
+        }
+        else synchronized (gcLock)
+        {
+            checkNoSync(p);
+        }
+    }
+
+
+    //
+    //
+    //
+    private void checkNoSync(void *p)
+    {
+        assert(p);
+
+        sentinel_Invariant(p);
+        debug (PTRCHECK)
+        {
+            Pool*  pool;
+            size_t pagenum;
+            Bins   bin;
+            size_t size;
+
+            p = sentinel_sub(p);
+            pool = gcx.findPool(p);
+            assert(pool);
+            pagenum = cast(size_t)(p - pool.baseAddr) / PAGESIZE;
+            bin = cast(Bins)pool.pagetable[pagenum];
+            assert(bin <= B_PAGE);
+            size = binsize[bin];
+            assert((cast(size_t)p & (size - 1)) == 0);
+
+            debug (PTRCHECK2)
+            {
+                if (bin < B_PAGE)
+                {
+                    // Check that p is not on a free list
+                    List *list;
+
+                    for (list = gcx.bucket[bin]; list; list = list.next)
+                    {
+                        assert(cast(void*)list != p);
+                    }
+                }
+            }
+        }
+    }
+
+
+    //
+    //
+    //
+    private void setStackBottom(void *p)
+    {
+        version (STACKGROWSDOWN)
+        {
+            //p = (void *)((uint *)p + 4);
+            if (p > gcx.stackBottom)
+            {
+                //debug(PRINTF) printf("setStackBottom(%x)\n", p);
+                gcx.stackBottom = p;
+            }
+        }
+        else
+        {
+            //p = (void *)((uint *)p - 4);
+            if (p < gcx.stackBottom)
+            {
+                //debug(PRINTF) printf("setStackBottom(%x)\n", p);
+                gcx.stackBottom = cast(char*)p;
+            }
+        }
+    }
+
+
+    /**
+     * add p to list of roots
+     */
+    void addRoot(void *p)
+    {
+        if (!p)
+        {
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+            gcx.addRoot(p);
+        }
+        else synchronized (gcLock)
+        {
+            gcx.addRoot(p);
+        }
+    }
+
+
+    /**
+     * remove p from list of roots
+     */
+    void removeRoot(void *p)
+    {
+        if (!p)
+        {
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+            gcx.removeRoot(p);
+        }
+        else synchronized (gcLock)
+        {
+            gcx.removeRoot(p);
+        }
+    }
+
+
+    /**
+     *
+     */
+    int delegate(int delegate(inout void*)) rootIter()
+    {
+        if (!thread_needLock())
+        {
+            return &gcx.rootIter;
+        }
+        else synchronized (gcLock)
+        {
+            return &gcx.rootIter;
+        }
+    }
+
+
+    /**
+     * add range to scan for roots
+     */
+    void addRange(void *p, size_t sz)
+    {
+        if (!p || !sz)
+        {
+            return;
+        }
+
+        //debug(PRINTF) printf("+GC.addRange(pbot = x%x, ptop = x%x)\n", pbot, ptop);
+        if (!thread_needLock())
+        {
+            gcx.addRange(p, p + sz);
+        }
+        else synchronized (gcLock)
+        {
+            gcx.addRange(p, p + sz);
+        }
+        //debug(PRINTF) printf("-GC.addRange()\n");
+    }
+
+
+    /**
+     * remove range
+     */
+    void removeRange(void *p)
+    {
+        if (!p)
+        {
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+            gcx.removeRange(p);
+        }
+        else synchronized (gcLock)
+        {
+            gcx.removeRange(p);
+        }
+    }
+
+
+    /**
+     *
+     */
+    int delegate(int delegate(inout Range)) rangeIter()
+    {
+        if (!thread_needLock())
+        {
+            return &gcx.rangeIter;
+        }
+        else synchronized (gcLock)
+        {
+            return &gcx.rangeIter;
+        }
+    }
+
+
+    /**
+     * do full garbage collection
+     */
+    void fullCollect()
+    {
+        debug(PRINTF) printf("GC.fullCollect()\n");
+
+        // Since a finalizer could launch a new thread, we always need to lock
+        // when collecting.
+        synchronized (gcLock)
+        {
+            gcx.fullcollectshell();
+        }
+
+        version (none)
+        {
+            GCStats stats;
+
+            getStats(stats);
+            debug(PRINTF) printf("poolsize = %x, usedsize = %x, freelistsize = %x\n",
+                    stats.poolsize, stats.usedsize, stats.freelistsize);
+        }
+
+        gcx.log_collect();
+    }
+
+
+    /**
+     * do full garbage collection ignoring roots
+     */
+    void fullCollectNoStack()
+    {
+        // Since a finalizer could launch a new thread, we always need to lock
+        // when collecting.
+        synchronized (gcLock)
+        {
+            gcx.noStack++;
+            gcx.fullcollectshell();
+            gcx.noStack--;
+        }
+    }
+
+
+    /**
+     * minimize free space usage
+     */
+    void minimize()
+    {
+        if (!thread_needLock())
+        {
+            gcx.minimize();
+        }
+        else synchronized (gcLock)
+        {
+            gcx.minimize();
+        }
+    }
+
+
+    /**
+     * Retrieve statistics about garbage collection.
+     * Useful for debugging and tuning.
+     */
+    void getStats(out GCStats stats)
+    {
+        if (!thread_needLock())
+        {
+            getStatsNoSync(stats);
+        }
+        else synchronized (gcLock)
+        {
+            getStatsNoSync(stats);
+        }
+    }
+
+
+    //
+    //
+    //
+    private void getStatsNoSync(out GCStats stats)
+    {
+        size_t psize = 0;
+        size_t usize = 0;
+        size_t flsize = 0;
+
+        size_t n;
+        size_t bsize = 0;
+
+        //debug(PRINTF) printf("getStats()\n");
+        memset(&stats, 0, GCStats.sizeof);
+
+        for (n = 0; n < gcx.npools; n++)
+        {   Pool *pool = gcx.pooltable[n];
+
+            psize += pool.ncommitted * PAGESIZE;
+            for (size_t j = 0; j < pool.ncommitted; j++)
+            {
+                Bins bin = cast(Bins)pool.pagetable[j];
+                if (bin == B_FREE)
+                    stats.freeblocks++;
+                else if (bin == B_PAGE)
+                    stats.pageblocks++;
+                else if (bin < B_PAGE)
+                    bsize += PAGESIZE;
+            }
+        }
+
+        for (n = 0; n < B_PAGE; n++)
+        {
+            //debug(PRINTF) printf("bin %d\n", n);
+            for (List *list = gcx.bucket[n]; list; list = list.next)
+            {
+                //debug(PRINTF) printf("\tlist %x\n", list);
+                flsize += binsize[n];
+            }
+        }
+
+        usize = bsize - flsize;
+
+        stats.poolsize = psize;
+        stats.usedsize = bsize - flsize;
+        stats.freelistsize = flsize;
+    }
+}
+
+
+/* ============================ Gcx =============================== */
+
+enum
+{   PAGESIZE =    4096,
+    COMMITSIZE = (4096*16),
+    POOLSIZE =   (4096*256),
+}
+
+
+enum
+{
+    B_16,
+    B_32,
+    B_64,
+    B_128,
+    B_256,
+    B_512,
+    B_1024,
+    B_2048,
+    B_PAGE,             // start of large alloc
+    B_PAGEPLUS,         // continuation of large alloc
+    B_FREE,             // free page
+    B_UNCOMMITTED,      // memory not committed for this page
+    B_MAX
+}
+
+
+alias ubyte Bins;
+
+
+struct List
+{
+    List *next;
+}
+
+
+struct Range
+{
+    void *pbot;
+    void *ptop;
+}
+
+
+immutable uint binsize[B_MAX] = [ 16,32,64,128,256,512,1024,2048,4096 ];
+immutable uint notbinsize[B_MAX] = [ ~(16u-1),~(32u-1),~(64u-1),~(128u-1),~(256u-1),
+                                ~(512u-1),~(1024u-1),~(2048u-1),~(4096u-1) ];
+
+/* ============================ Gcx =============================== */
+
+
+struct Gcx
+{
+    debug (THREADINVARIANT)
+    {
+        pthread_t self;
+        void thread_Invariant()
+        {
+            if (self != pthread_self())
+                printf("thread_Invariant(): gcx = %x, self = %x, pthread_self() = %x\n", this, self, pthread_self());
+            assert(self == pthread_self());
+        }
+    }
+    else
+    {
+        void thread_Invariant() { }
+    }
+
+    void *p_cache;
+    size_t size_cache;
+
+    size_t nroots;
+    size_t rootdim;
+    void **roots;
+
+    size_t nranges;
+    size_t rangedim;
+    Range *ranges;
+
+    uint noStack;       // !=0 means don't scan stack
+    uint log;           // turn on logging
+    uint anychanges;
+    void *stackBottom;
+    uint inited;
+    int disabled;       // turn off collections if >0
+
+    byte *minAddr;      // min(baseAddr)
+    byte *maxAddr;      // max(topAddr)
+
+    size_t npools;
+    Pool **pooltable;
+
+    List *bucket[B_MAX];        // free list for each size
+
+
+    void initialize()
+    {   int dummy;
+
+        (cast(byte*)&this)[0 .. Gcx.sizeof] = 0;
+        stackBottom = cast(char*)&dummy;
+        log_init();
+        debug (THREADINVARIANT)
+            self = pthread_self();
+        //printf("gcx = %p, self = %x\n", this, self);
+        inited = 1;
+    }
+
+
+    void Dtor()
+    {
+        inited = 0;
+
+        for (size_t i = 0; i < npools; i++)
+        {   Pool *pool = pooltable[i];
+
+            pool.Dtor();
+            cstdlib.free(pool);
+        }
+        if (pooltable)
+            cstdlib.free(pooltable);
+
+        if (roots)
+            cstdlib.free(roots);
+
+        if (ranges)
+            cstdlib.free(ranges);
+    }
+
+
+    void Invariant() { }
+
+
+    invariant()
+    {
+        if (inited)
+        {
+        //printf("Gcx.invariant(): this = %p\n", this);
+            size_t i;
+
+            // Assure we're called on the right thread
+            debug (THREADINVARIANT) assert(self == pthread_self());
+
+            for (i = 0; i < npools; i++)
+            {   Pool *pool = pooltable[i];
+
+                pool.Invariant();
+                if (i == 0)
+                {
+                    assert(minAddr == pool.baseAddr);
+                }
+                if (i + 1 < npools)
+                {
+                    assert(pool.opCmp(pooltable[i + 1]) < 0);
+                }
+                else if (i + 1 == npools)
+                {
+                    assert(maxAddr == pool.topAddr);
+                }
+            }
+
+            if (roots)
+            {
+                assert(rootdim != 0);
+                assert(nroots <= rootdim);
+            }
+
+            if (ranges)
+            {
+                assert(rangedim != 0);
+                assert(nranges <= rangedim);
+
+                for (i = 0; i < nranges; i++)
+                {
+                    assert(ranges[i].pbot);
+                    assert(ranges[i].ptop);
+                    assert(ranges[i].pbot <= ranges[i].ptop);
+                }
+            }
+
+            for (i = 0; i < B_PAGE; i++)
+            {
+                for (List *list = bucket[i]; list; list = list.next)
+                {
+                }
+            }
+        }
+    }
+
+
+    /**
+     *
+     */
+    void addRoot(void *p)
+    {
+        if (nroots == rootdim)
+        {
+            size_t newdim = rootdim * 2 + 16;
+            void** newroots;
+
+            newroots = cast(void**)cstdlib.malloc(newdim * newroots[0].sizeof);
+            if (!newroots)
+                onOutOfMemoryError();
+            if (roots)
+            {   memcpy(newroots, roots, nroots * newroots[0].sizeof);
+                cstdlib.free(roots);
+            }
+            roots = newroots;
+            rootdim = newdim;
+        }
+        roots[nroots] = p;
+        nroots++;
+    }
+
+
+    /**
+     *
+     */
+    void removeRoot(void *p)
+    {
+        for (size_t i = nroots; i--;)
+        {
+            if (roots[i] == p)
+            {
+                nroots--;
+                memmove(roots + i, roots + i + 1, (nroots - i) * roots[0].sizeof);
+                return;
+            }
+        }
+        assert(0);
+    }
+
+
+    /**
+     *
+     */
+    int rootIter(int delegate(inout void*) dg)
+    {
+        int result = 0;
+        for( size_t i = 0; i < nroots; ++i )
+        {
+            result = dg(roots[i]);
+            if (result)
+                break;
+        }
+        return result;
+    }
+
+
+    /**
+     *
+     */
+    void addRange(void *pbot, void *ptop)
+    {
+        //debug(PRINTF) printf("Thread %x ", pthread_self());
+        debug(PRINTF) printf("%x.Gcx::addRange(%x, %x), nranges = %d\n", this, pbot, ptop, nranges);
+        if (nranges == rangedim)
+        {
+            size_t newdim = rangedim * 2 + 16;
+            Range *newranges;
+
+            newranges = cast(Range*)cstdlib.malloc(newdim * newranges[0].sizeof);
+            if (!newranges)
+                onOutOfMemoryError();
+            if (ranges)
+            {   memcpy(newranges, ranges, nranges * newranges[0].sizeof);
+                cstdlib.free(ranges);
+            }
+            ranges = newranges;
+            rangedim = newdim;
+        }
+        ranges[nranges].pbot = pbot;
+        ranges[nranges].ptop = ptop;
+        nranges++;
+    }
+
+
+    /**
+     *
+     */
+    void removeRange(void *pbot)
+    {
+        //debug(PRINTF) printf("Thread %x ", pthread_self());
+        debug(PRINTF) printf("%x.Gcx.removeRange(%x), nranges = %d\n", this, pbot, nranges);
+        for (size_t i = nranges; i--;)
+        {
+            if (ranges[i].pbot == pbot)
+            {
+                nranges--;
+                memmove(ranges + i, ranges + i + 1, (nranges - i) * ranges[0].sizeof);
+                return;
+            }
+        }
+        debug(PRINTF) printf("Wrong thread\n");
+
+        // This is a fatal error, but ignore it.
+        // The problem is that we can get a Close() call on a thread
+        // other than the one the range was allocated on.
+        //assert(zero);
+    }
+
+
+    /**
+     *
+     */
+    int rangeIter(int delegate(inout Range) dg)
+    {
+        int result = 0;
+        for( size_t i = 0; i < nranges; ++i )
+        {
+            result = dg(ranges[i]);
+            if (result)
+                break;
+        }
+        return result;
+    }
+
+
+    /**
+     * Find Pool that pointer is in.
+     * Return null if not in a Pool.
+     * Assume pooltable[] is sorted.
+     */
+    Pool *findPool(void *p)
+    {
+        if (p >= minAddr && p < maxAddr)
+        {
+            if (npools == 1)
+            {
+                return pooltable[0];
+            }
+
+            for (size_t i = 0; i < npools; i++)
+            {   Pool *pool;
+
+                pool = pooltable[i];
+                if (p < pool.topAddr)
+                {   if (pool.baseAddr <= p)
+                        return pool;
+                    break;
+                }
+            }
+        }
+        return null;
+    }
+
+
+    /**
+     * Find base address of block containing pointer p.
+     * Returns null if not a gc'd pointer
+     */
+    void* findBase(void *p)
+    {
+        Pool *pool;
+
+        pool = findPool(p);
+        if (pool)
+        {
+            size_t offset = cast(size_t)(p - pool.baseAddr);
+            size_t pn = offset / PAGESIZE;
+            Bins   bin = cast(Bins)pool.pagetable[pn];
+
+            // Adjust bit to be at start of allocated memory block
+            if (bin <= B_PAGE)
+            {
+                return pool.baseAddr + (offset & notbinsize[bin]);
+            }
+            else if (bin == B_PAGEPLUS)
+            {
+                do
+                {   --pn, offset -= PAGESIZE;
+                } while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS);
+
+                return pool.baseAddr + (offset & (offset.max ^ (PAGESIZE-1)));
+            }
+            else
+            {
+                // we are in a B_FREE or B_UNCOMMITTED page
+                return null;
+            }
+        }
+        return null;
+    }
+
+
+    /**
+     * Find size of pointer p.
+     * Returns 0 if not a gc'd pointer
+     */
+    size_t findSize(void *p)
+    {
+        Pool*  pool;
+        size_t size = 0;
+
+        pool = findPool(p);
+        if (pool)
+        {
+            size_t pagenum;
+            Bins   bin;
+
+            pagenum = cast(size_t)(p - pool.baseAddr) / PAGESIZE;
+            bin = cast(Bins)pool.pagetable[pagenum];
+            size = binsize[bin];
+            if (bin == B_PAGE)
+            {   size_t npages = pool.ncommitted;
+                ubyte* pt;
+                size_t i;
+
+                pt = &pool.pagetable[0];
+                for (i = pagenum + 1; i < npages; i++)
+                {
+                    if (pt[i] != B_PAGEPLUS)
+                        break;
+                }
+                size = (i - pagenum) * PAGESIZE;
+            }
+        }
+        return size;
+    }
+
+
+    /**
+     *
+     */
+    BlkInfo getInfo(void* p)
+    {
+        Pool*   pool;
+        BlkInfo info;
+
+        pool = findPool(p);
+        if (pool)
+        {
+            size_t offset = cast(size_t)(p - pool.baseAddr);
+            size_t pn = offset / PAGESIZE;
+            Bins   bin = cast(Bins)pool.pagetable[pn];
+
+            ////////////////////////////////////////////////////////////////////
+            // findAddr
+            ////////////////////////////////////////////////////////////////////
+
+            if (bin <= B_PAGE)
+            {
+                info.base = pool.baseAddr + (offset & notbinsize[bin]);
+            }
+            else if (bin == B_PAGEPLUS)
+            {
+                do
+                {   --pn, offset -= PAGESIZE;
+                } while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS);
+
+                info.base = pool.baseAddr + (offset & (offset.max ^ (PAGESIZE-1)));
+
+                // fix bin for use by size calc below
+                bin = cast(Bins)pool.pagetable[pn];
+            }
+
+            ////////////////////////////////////////////////////////////////////
+            // findSize
+            ////////////////////////////////////////////////////////////////////
+
+            info.size = binsize[bin];
+            if (bin == B_PAGE)
+            {   size_t npages = pool.ncommitted;
+                ubyte* pt;
+                size_t i;
+
+                pt = &pool.pagetable[0];
+                for (i = pn + 1; i < npages; i++)
+                {
+                    if (pt[i] != B_PAGEPLUS)
+                        break;
+                }
+                info.size = (i - pn) * PAGESIZE;
+            }
+
+            ////////////////////////////////////////////////////////////////////
+            // getBits
+            ////////////////////////////////////////////////////////////////////
+
+            info.attr = getBits(pool, cast(size_t)(offset / 16));
+        }
+        return info;
+    }
+
+
+    /**
+     * Compute bin for size.
+     */
+    static Bins findBin(size_t size)
+    {   Bins bin;
+
+        if (size <= 256)
+        {
+            if (size <= 64)
+            {
+                if (size <= 16)
+                    bin = B_16;
+                else if (size <= 32)
+                    bin = B_32;
+                else
+                    bin = B_64;
+            }
+            else
+            {
+                if (size <= 128)
+                    bin = B_128;
+                else
+                    bin = B_256;
+            }
+        }
+        else
+        {
+            if (size <= 1024)
+            {
+                if (size <= 512)
+                    bin = B_512;
+                else
+                    bin = B_1024;
+            }
+            else
+            {
+                if (size <= 2048)
+                    bin = B_2048;
+                else
+                    bin = B_PAGE;
+            }
+        }
+        return bin;
+    }
+
+
+    /**
+     * Allocate a new pool of at least size bytes.
+     * Sort it into pooltable[].
+     * Mark all memory in the pool as B_FREE.
+     * Return the actual number of bytes reserved or 0 on error.
+     */
+    size_t reserve(size_t size)
+    {
+        size_t npages = (size + PAGESIZE - 1) / PAGESIZE;
+        Pool*  pool = newPool(npages);
+
+        if (!pool || pool.extendPages(npages) == OPFAIL)
+            return 0;
+        return pool.ncommitted * PAGESIZE;
+    }
+
+
+    /**
+     * Minimizes physical memory usage by returning free pools to the OS.
+     */
+    void minimize()
+    {
+        size_t n;
+        size_t pn;
+        Pool*  pool;
+        size_t ncommitted;
+
+        for (n = 0; n < npools; n++)
+        {
+            pool = pooltable[n];
+            ncommitted = pool.ncommitted;
+            for (pn = 0; pn < ncommitted; pn++)
+            {
+                if (cast(Bins)pool.pagetable[pn] != B_FREE)
+                    break;
+            }
+            if (pn < ncommitted)
+            {
+                n++;
+                continue;
+            }
+            pool.Dtor();
+            cstdlib.free(pool);
+            memmove(pooltable + n,
+                    pooltable + n + 1,
+                    (--npools - n) * (Pool*).sizeof);
+            minAddr = pooltable[0].baseAddr;
+            maxAddr = pooltable[npools - 1].topAddr;
+        }
+    }
+
+
+    /**
+     * Allocate a chunk of memory that is larger than a page.
+     * Return null if out of memory.
+     */
+    void *bigAlloc(size_t size)
+    {
+        Pool*  pool;
+        size_t npages;
+        size_t n;
+        size_t pn;
+        size_t freedpages;
+        void*  p;
+        int    state;
+        bool   collected = false;
+
+        npages = (size + PAGESIZE - 1) / PAGESIZE;
+
+        for (state = disabled ? 1 : 0; ; )
+        {
+            // This code could use some refinement when repeatedly
+            // allocating very large arrays.
+
+            for (n = 0; n < npools; n++)
+            {
+                pool = pooltable[n];
+                pn = pool.allocPages(npages);
+                if (pn != OPFAIL)
+                    goto L1;
+            }
+
+            // Failed
+            switch (state)
+            {
+            case 0:
+                // Try collecting
+                collected = true;
+                freedpages = fullcollectshell();
+                if (freedpages >= npools * ((POOLSIZE / PAGESIZE) / 4))
+                {   state = 1;
+                    continue;
+                }
+                // Release empty pools to prevent bloat
+                minimize();
+                // Allocate new pool
+                pool = newPool(npages);
+                if (!pool)
+                {   state = 2;
+                    continue;
+                }
+                pn = pool.allocPages(npages);
+                assert(pn != OPFAIL);
+                goto L1;
+            case 1:
+                // Release empty pools to prevent bloat
+                minimize();
+                // Allocate new pool
+                pool = newPool(npages);
+                if (!pool)
+                {
+                    if (collected)
+                        goto Lnomemory;
+                    state = 0;
+                    continue;
+                }
+                pn = pool.allocPages(npages);
+                assert(pn != OPFAIL);
+                goto L1;
+            case 2:
+                goto Lnomemory;
+            default:
+                assert(false);
+            }
+        }
+
+      L1:
+        pool.pagetable[pn] = B_PAGE;
+        if (npages > 1)
+            memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1);
+        p = pool.baseAddr + pn * PAGESIZE;
+        memset(cast(char *)p + size, 0, npages * PAGESIZE - size);
+        debug (MEMSTOMP) memset(p, 0xF1, size);
+        //debug(PRINTF) printf("\tp = %x\n", p);
+        return p;
+
+      Lnomemory:
+        return null; // let caller handle the error
+    }
+
+
+    /**
+     * Allocate a new pool with at least npages in it.
+     * Sort it into pooltable[].
+     * Return null if failed.
+     */
+    Pool *newPool(size_t npages)
+    {
+        Pool*  pool;
+        Pool** newpooltable;
+        size_t newnpools;
+        size_t i;
+
+        //debug(PRINTF) printf("************Gcx::newPool(npages = %d)****************\n", npages);
+
+        // Round up to COMMITSIZE pages
+        npages = (npages + (COMMITSIZE/PAGESIZE) - 1) & ~(COMMITSIZE/PAGESIZE - 1);
+
+        // Minimum of POOLSIZE
+        if (npages < POOLSIZE/PAGESIZE)
+            npages = POOLSIZE/PAGESIZE;
+        else if (npages > POOLSIZE/PAGESIZE)
+        {   // Give us 150% of requested size, so there's room to extend
+            auto n = npages + (npages >> 1);
+            if (n < size_t.max/PAGESIZE)
+                npages = n;
+        }
+
+        // Allocate successively larger pools up to 8 megs
+        if (npools)
+        {   size_t n;
+
+            n = npools;
+            if (n > 8)
+                n = 8;                  // cap pool size at 8 megs
+            n *= (POOLSIZE / PAGESIZE);
+            if (npages < n)
+                npages = n;
+        }
+
+        pool = cast(Pool *)cstdlib.calloc(1, Pool.sizeof);
+        if (pool)
+        {
+            pool.initialize(npages);
+            if (!pool.baseAddr)
+                goto Lerr;
+
+            newnpools = npools + 1;
+            newpooltable = cast(Pool **)cstdlib.realloc(pooltable, newnpools * (Pool *).sizeof);
+            if (!newpooltable)
+                goto Lerr;
+
+            // Sort pool into newpooltable[]
+            for (i = 0; i < npools; i++)
+            {
+                if (pool.opCmp(newpooltable[i]) < 0)
+                     break;
+            }
+            memmove(newpooltable + i + 1, newpooltable + i, (npools - i) * (Pool *).sizeof);
+            newpooltable[i] = pool;
+
+            pooltable = newpooltable;
+            npools = newnpools;
+
+            minAddr = pooltable[0].baseAddr;
+            maxAddr = pooltable[npools - 1].topAddr;
+        }
+        return pool;
+
+      Lerr:
+        pool.Dtor();
+        cstdlib.free(pool);
+        return null;
+    }
+
+
+    /**
+     * Allocate a page of bin's.
+     * Returns:
+     *  0       failed
+     */
+    int allocPage(Bins bin)
+    {
+        Pool*  pool;
+        size_t n;
+        size_t pn;
+        byte*  p;
+        byte*  ptop;
+
+        //debug(PRINTF) printf("Gcx::allocPage(bin = %d)\n", bin);
+        for (n = 0; n < npools; n++)
+        {
+            pool = pooltable[n];
+            pn = pool.allocPages(1);
+            if (pn != OPFAIL)
+                goto L1;
+        }
+        return 0;               // failed
+
+      L1:
+        pool.pagetable[pn] = cast(ubyte)bin;
+
+        // Convert page to free list
+        size_t size = binsize[bin];
+        List **b = &bucket[bin];
+
+        p = pool.baseAddr + pn * PAGESIZE;
+        ptop = p + PAGESIZE;
+        for (; p < ptop; p += size)
+        {
+            (cast(List *)p).next = *b;
+            *b = cast(List *)p;
+        }
+        return 1;
+    }
+
+
+    /**
+     * Search a range of memory values and mark any pointers into the GC pool.
+     */
+    void mark(void *pbot, void *ptop)
+    {
+        void **p1 = cast(void **)pbot;
+        void **p2 = cast(void **)ptop;
+        size_t pcache = 0;
+        uint changes = 0;
+
+        //printf("marking range: %p -> %p\n", pbot, ptop);
+        for (; p1 < p2; p1++)
+        {
+            Pool *pool;
+            byte *p = cast(byte *)(*p1);
+
+            //if (log) debug(PRINTF) printf("\tmark %x\n", p);
+            if (p >= minAddr && p < maxAddr)
+            {
+                if ((cast(size_t)p & ~(PAGESIZE-1)) == pcache)
+                    continue;
+
+                pool = findPool(p);
+                if (pool)
+                {
+                    size_t offset = cast(size_t)(p - pool.baseAddr);
+                    size_t biti;
+                    size_t pn = offset / PAGESIZE;
+                    Bins   bin = cast(Bins)pool.pagetable[pn];
+
+                    //debug(PRINTF) printf("\t\tfound pool %x, base=%x, pn = %d, bin = %d, biti = x%x\n", pool, pool.baseAddr, pn, bin, biti);
+
+                    // Adjust bit to be at start of allocated memory block
+                    if (bin <= B_PAGE)
+                    {
+                        biti = (offset & notbinsize[bin]) >> 4;
+                        //debug(PRINTF) printf("\t\tbiti = x%x\n", biti);
+                    }
+                    else if (bin == B_PAGEPLUS)
+                    {
+                        do
+                        {   --pn;
+                        } while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS);
+                        biti = pn * (PAGESIZE / 16);
+                    }
+                    else
+                    {
+                        // Don't mark bits in B_FREE or B_UNCOMMITTED pages
+                        continue;
+                    }
+
+                    if (bin >= B_PAGE) // Cache B_PAGE and B_PAGEPLUS lookups
+                        pcache = cast(size_t)p & ~(PAGESIZE-1);
+
+                    //debug(PRINTF) printf("\t\tmark(x%x) = %d\n", biti, pool.mark.test(biti));
+                    if (!pool.mark.test(biti))
+                    {
+                        //if (log) debug(PRINTF) printf("\t\tmarking %x\n", p);
+                        pool.mark.set(biti);
+                        if (!pool.noscan.test(biti))
+                        {
+                            pool.scan.set(biti);
+                            changes = 1;
+                        }
+                        log_parent(sentinel_add(pool.baseAddr + biti * 16), sentinel_add(pbot));
+                    }
+                }
+            }
+        }
+        anychanges |= changes;
+    }
+
+
+    /**
+     * Return number of full pages free'd.
+     */
+    size_t fullcollectshell()
+    {
+        // The purpose of the 'shell' is to ensure all the registers
+        // get put on the stack so they'll be scanned
+        void *sp;
+        size_t result;
+        version (GNU)
+        {
+            __builtin_unwind_init();
+            sp = & sp;
+        }
+        else
+        {
+        asm
+        {
+            pushad              ;
+            mov sp[EBP],ESP     ;
+        }
+        }
+        result = fullcollect(sp);
+        version (GNU)
+        {
+            // nothing to do
+        }
+        else
+        {
+        asm
+        {
+            popad               ;
+        }
+        }
+        return result;
+    }
+
+
+    /**
+     *
+     */
+    size_t fullcollect(void *stackTop)
+    {
+        size_t n;
+        Pool*  pool;
+
+        debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n");
+
+        thread_suspendAll();
+
+        p_cache = null;
+        size_cache = 0;
+
+        anychanges = 0;
+        for (n = 0; n < npools; n++)
+        {
+            pool = pooltable[n];
+            pool.mark.zero();
+            pool.scan.zero();
+            pool.freebits.zero();
+        }
+
+        // Mark each free entry, so it doesn't get scanned
+        for (n = 0; n < B_PAGE; n++)
+        {
+            for (List *list = bucket[n]; list; list = list.next)
+            {
+                pool = findPool(list);
+                assert(pool);
+                pool.freebits.set(cast(size_t)(cast(byte*)list - pool.baseAddr) / 16);
+            }
+        }
+
+        for (n = 0; n < npools; n++)
+        {
+            pool = pooltable[n];
+            pool.mark.copy(&pool.freebits);
+        }
+
+        version (MULTI_THREADED)
+        {
+            if (!noStack)
+            {
+                // Scan stacks and registers for each paused thread
+                thread_scanAll( &mark, stackTop );
+            }
+        }
+        else
+        {
+            if (!noStack)
+            {
+                // Scan stack for main thread
+                debug(PRINTF) printf(" scan stack bot = %x, top = %x\n", stackTop, stackBottom);
+                version (STACKGROWSDOWN)
+                    mark(stackTop, stackBottom);
+                else
+                    mark(stackBottom, stackTop);
+            }
+        }
+
+        // Scan roots[]
+        debug(COLLECT_PRINTF) printf("scan roots[]\n");
+        mark(roots, roots + nroots);
+
+        // Scan ranges[]
+        debug(COLLECT_PRINTF) printf("scan ranges[]\n");
+        //log++;
+        for (n = 0; n < nranges; n++)
+        {
+            debug(COLLECT_PRINTF) printf("\t%x .. %x\n", ranges[n].pbot, ranges[n].ptop);
+            mark(ranges[n].pbot, ranges[n].ptop);
+        }
+        //log--;
+
+        debug(COLLECT_PRINTF) printf("\tscan heap\n");
+        while (anychanges)
+        {
+            anychanges = 0;
+            for (n = 0; n < npools; n++)
+            {
+                uint *bbase;
+                uint *b;
+                uint *btop;
+
+                pool = pooltable[n];
+
+                bbase = pool.scan.base();
+                btop = bbase + pool.scan.nwords;
+                for (b = bbase; b < btop;)
+                {   Bins   bin;
+                    size_t pn;
+                    size_t u;
+                    size_t bitm;
+                    byte*  o;
+
+                    bitm = *b;
+                    if (!bitm)
+                    {   b++;
+                        continue;
+                    }
+                    *b = 0;
+
+                    o = pool.baseAddr + (b - bbase) * 32 * 16;
+                    if (!(bitm & 0xFFFF))
+                    {
+                        bitm >>= 16;
+                        o += 16 * 16;
+                    }
+                    for (; bitm; o += 16, bitm >>= 1)
+                    {
+                        if (!(bitm & 1))
+                            continue;
+
+                        pn = cast(size_t)(o - pool.baseAddr) / PAGESIZE;
+                        bin = cast(Bins)pool.pagetable[pn];
+                        if (bin < B_PAGE)
+                        {
+                            mark(o, o + binsize[bin]);
+                        }
+                        else if (bin == B_PAGE || bin == B_PAGEPLUS)
+                        {
+                            if (bin == B_PAGEPLUS)
+                            {
+                                while (pool.pagetable[pn - 1] != B_PAGE)
+                                    pn--;
+                            }
+                            u = 1;
+                            while (pn + u < pool.ncommitted && pool.pagetable[pn + u] == B_PAGEPLUS)
+                                u++;
+                            mark(o, o + u * PAGESIZE);
+                        }
+                    }
+                }
+            }
+        }
+
+        thread_resumeAll();
+
+        // Free up everything not marked
+        debug(COLLECT_PRINTF) printf("\tfree'ing\n");
+        size_t freedpages = 0;
+        size_t freed = 0;
+        for (n = 0; n < npools; n++)
+        {   size_t pn;
+            size_t ncommitted;
+            uint*  bbase;
+
+            pool = pooltable[n];
+            bbase = pool.mark.base();
+            ncommitted = pool.ncommitted;
+            for (pn = 0; pn < ncommitted; pn++, bbase += PAGESIZE / (32 * 16))
+            {
+                Bins bin = cast(Bins)pool.pagetable[pn];
+
+                if (bin < B_PAGE)
+                {   byte* p;
+                    byte* ptop;
+                    size_t biti;
+                    size_t bitstride;
+                    auto   size = binsize[bin];
+
+                    p = pool.baseAddr + pn * PAGESIZE;
+                    ptop = p + PAGESIZE;
+                    biti = pn * (PAGESIZE/16);
+                    bitstride = size / 16;
+
+    version(none) // BUG: doesn't work because freebits() must also be cleared
+    {
+                    // If free'd entire page
+                    if (bbase[0] == 0 && bbase[1] == 0 && bbase[2] == 0 && bbase[3] == 0 &&
+                        bbase[4] == 0 && bbase[5] == 0 && bbase[6] == 0 && bbase[7] == 0)
+                    {
+                        for (; p < ptop; p += size, biti += bitstride)
+                        {
+                            if (pool.finals.nbits && pool.finals.testClear(biti))
+                                rt_finalize(cast(List *)sentinel_add(p), false/*noStack > 0*/);
+                            gcx.clrBits(pool, biti, BlkAttr.ALL_BITS);
+
+                            List *list = cast(List *)p;
+                            //debug(PRINTF) printf("\tcollecting %x\n", list);
+                            log_free(sentinel_add(list));
+
+                            debug (MEMSTOMP) memset(p, 0xF3, size);
+                        }
+                        pool.pagetable[pn] = B_FREE;
+                        freed += PAGESIZE;
+                        //debug(PRINTF) printf("freeing entire page %d\n", pn);
+                        continue;
+                    }
+    }
+                    for (; p < ptop; p += size, biti += bitstride)
+                    {
+                        if (!pool.mark.test(biti))
+                        {
+                            sentinel_Invariant(sentinel_add(p));
+
+                            pool.freebits.set(biti);
+                            if (pool.finals.nbits && pool.finals.testClear(biti))
+                                rt_finalize(cast(List *)sentinel_add(p), false/*noStack > 0*/);
+                            clrBits(pool, biti, BlkAttr.ALL_BITS);
+
+                            List *list = cast(List *)p;
+                            debug(PRINTF) printf("\tcollecting %x\n", list);
+                            log_free(sentinel_add(list));
+
+                            debug (MEMSTOMP) memset(p, 0xF3, size);
+
+                            freed += size;
+                        }
+                    }
+                }
+                else if (bin == B_PAGE)
+                {   size_t biti = pn * (PAGESIZE / 16);
+
+                    if (!pool.mark.test(biti))
+                    {   byte *p = pool.baseAddr + pn * PAGESIZE;
+
+                        sentinel_Invariant(sentinel_add(p));
+                        if (pool.finals.nbits && pool.finals.testClear(biti))
+                            rt_finalize(sentinel_add(p), false/*noStack > 0*/);
+                        clrBits(pool, biti, BlkAttr.ALL_BITS);
+
+                        debug(COLLECT_PRINTF) printf("\tcollecting big %x\n", p);
+                        log_free(sentinel_add(p));
+                        pool.pagetable[pn] = B_FREE;
+                        freedpages++;
+                        debug (MEMSTOMP) memset(p, 0xF3, PAGESIZE);
+                        while (pn + 1 < ncommitted && pool.pagetable[pn + 1] == B_PAGEPLUS)
+                        {
+                            pn++;
+                            pool.pagetable[pn] = B_FREE;
+                            freedpages++;
+
+                            debug (MEMSTOMP)
+                            {   p += PAGESIZE;
+                                memset(p, 0xF3, PAGESIZE);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // Zero buckets
+        bucket[] = null;
+
+        // Free complete pages, rebuild free list
+        debug(COLLECT_PRINTF) printf("\tfree complete pages\n");
+        size_t recoveredpages = 0;
+        for (n = 0; n < npools; n++)
+        {   size_t pn;
+            size_t ncommitted;
+
+            pool = pooltable[n];
+            ncommitted = pool.ncommitted;
+            for (pn = 0; pn < ncommitted; pn++)
+            {
+                Bins   bin = cast(Bins)pool.pagetable[pn];
+                size_t biti;
+                size_t u;
+
+                if (bin < B_PAGE)
+                {
+                    size_t size = binsize[bin];
+                    size_t bitstride = size / 16;
+                    size_t bitbase = pn * (PAGESIZE / 16);
+                    size_t bittop = bitbase + (PAGESIZE / 16);
+                    byte*  p;
+
+                    biti = bitbase;
+                    for (biti = bitbase; biti < bittop; biti += bitstride)
+                    {   if (!pool.freebits.test(biti))
+                            goto Lnotfree;
+                    }
+                    pool.pagetable[pn] = B_FREE;
+                    recoveredpages++;
+                    continue;
+
+                 Lnotfree:
+                    p = pool.baseAddr + pn * PAGESIZE;
+                    for (u = 0; u < PAGESIZE; u += size)
+                    {   biti = bitbase + u / 16;
+                        if (pool.freebits.test(biti))
+                        {   List *list;
+
+                            list = cast(List *)(p + u);
+                            if (list.next != bucket[bin])       // avoid unnecessary writes
+                                list.next = bucket[bin];
+                            bucket[bin] = list;
+                        }
+                    }
+                }
+            }
+        }
+
+        debug(COLLECT_PRINTF) printf("recovered pages = %d\n", recoveredpages);
+        debug(COLLECT_PRINTF) printf("\tfree'd %u bytes, %u pages from %u pools\n", freed, freedpages, npools);
+
+        return freedpages + recoveredpages;
+    }
+
+
+    /**
+     *
+     */
+    uint getBits(Pool* pool, size_t biti)
+    in
+    {
+        assert( pool );
+    }
+    body
+    {
+        uint bits;
+
+        if (pool.finals.nbits &&
+            pool.finals.test(biti))
+            bits |= BlkAttr.FINALIZE;
+        if (pool.noscan.test(biti))
+            bits |= BlkAttr.NO_SCAN;
+//        if (pool.nomove.nbits &&
+//            pool.nomove.test(biti))
+//            bits |= BlkAttr.NO_MOVE;
+        return bits;
+    }
+
+
+    /**
+     *
+     */
+    void setBits(Pool* pool, size_t biti, uint mask)
+    in
+    {
+        assert( pool );
+    }
+    body
+    {
+        if (mask & BlkAttr.FINALIZE)
+        {
+            if (!pool.finals.nbits)
+                pool.finals.alloc(pool.mark.nbits);
+            pool.finals.set(biti);
+        }
+        if (mask & BlkAttr.NO_SCAN)
+        {
+            pool.noscan.set(biti);
+        }
+//        if (mask & BlkAttr.NO_MOVE)
+//        {
+//            if (!pool.nomove.nbits)
+//                pool.nomove.alloc(pool.mark.nbits);
+//            pool.nomove.set(biti);
+//        }
+    }
+
+
+    /**
+     *
+     */
+    void clrBits(Pool* pool, size_t biti, uint mask)
+    in
+    {
+        assert( pool );
+    }
+    body
+    {
+        if (mask & BlkAttr.FINALIZE && pool.finals.nbits)
+            pool.finals.clear(biti);
+        if (mask & BlkAttr.NO_SCAN)
+            pool.noscan.clear(biti);
+//        if (mask & BlkAttr.NO_MOVE && pool.nomove.nbits)
+//            pool.nomove.clear(biti);
+    }
+
+
+    /***** Leak Detector ******/
+
+
+    debug (LOGGING)
+    {
+        LogArray current;
+        LogArray prev;
+
+
+        void log_init()
+        {
+            //debug(PRINTF) printf("+log_init()\n");
+            current.reserve(1000);
+            prev.reserve(1000);
+            //debug(PRINTF) printf("-log_init()\n");
+        }
+
+
+        void log_malloc(void *p, size_t size)
+        {
+            //debug(PRINTF) printf("+log_malloc(p = %x, size = %d)\n", p, size);
+            Log log;
+
+            log.p = p;
+            log.size = size;
+            log.line = GC.line;
+            log.file = GC.file;
+            log.parent = null;
+
+            GC.line = 0;
+            GC.file = null;
+
+            current.push(log);
+            //debug(PRINTF) printf("-log_malloc()\n");
+        }
+
+
+        void log_free(void *p)
+        {
+            //debug(PRINTF) printf("+log_free(%x)\n", p);
+            size_t i;
+
+            i = current.find(p);
+            if (i == OPFAIL)
+            {
+                debug(PRINTF) printf("free'ing unallocated memory %x\n", p);
+            }
+            else
+                current.remove(i);
+            //debug(PRINTF) printf("-log_free()\n");
+        }
+
+
+        void log_collect()
+        {
+            //debug(PRINTF) printf("+log_collect()\n");
+            // Print everything in current that is not in prev
+
+            debug(PRINTF) printf("New pointers this cycle: --------------------------------\n");
+            size_t used = 0;
+            for (size_t i = 0; i < current.dim; i++)
+            {
+                size_t j;
+
+                j = prev.find(current.data[i].p);
+                if (j == OPFAIL)
+                    current.data[i].print();
+                else
+                    used++;
+            }
+
+            debug(PRINTF) printf("All roots this cycle: --------------------------------\n");
+            for (size_t i = 0; i < current.dim; i++)
+            {
+                void *p;
+                size_t j;
+
+                p = current.data[i].p;
+                if (!findPool(current.data[i].parent))
+                {
+                    j = prev.find(current.data[i].p);
+                    if (j == OPFAIL)
+                        debug(PRINTF) printf("N");
+                    else
+                        debug(PRINTF) printf(" ");;
+                    current.data[i].print();
+                }
+            }
+
+            debug(PRINTF) printf("Used = %d-------------------------------------------------\n", used);
+            prev.copy(&current);
+
+            debug(PRINTF) printf("-log_collect()\n");
+        }
+
+
+        void log_parent(void *p, void *parent)
+        {
+            //debug(PRINTF) printf("+log_parent()\n");
+            size_t i;
+
+            i = current.find(p);
+            if (i == OPFAIL)
+            {
+                debug(PRINTF) printf("parent'ing unallocated memory %x, parent = %x\n", p, parent);
+                Pool *pool;
+                pool = findPool(p);
+                assert(pool);
+                size_t offset = cast(size_t)(p - pool.baseAddr);
+                size_t biti;
+                size_t pn = offset / PAGESIZE;
+                Bins bin = cast(Bins)pool.pagetable[pn];
+                biti = (offset & notbinsize[bin]);
+                debug(PRINTF) printf("\tbin = %d, offset = x%x, biti = x%x\n", bin, offset, biti);
+            }
+            else
+            {
+                current.data[i].parent = parent;
+            }
+            //debug(PRINTF) printf("-log_parent()\n");
+        }
+
+    }
+    else
+    {
+        void log_init() { }
+        void log_malloc(void *p, size_t size) { }
+        void log_free(void *p) { }
+        void log_collect() { }
+        void log_parent(void *p, void *parent) { }
+    }
+}
+
+
+/* ============================ Pool  =============================== */
+
+
+struct Pool
+{
+    byte* baseAddr;
+    byte* topAddr;
+    GCBits mark;        // entries already scanned, or should not be scanned
+    GCBits scan;        // entries that need to be scanned
+    GCBits freebits;    // entries that are on the free list
+    GCBits finals;      // entries that need finalizer run on them
+    GCBits noscan;      // entries that should not be scanned
+
+    size_t npages;
+    size_t ncommitted;    // ncommitted <= npages
+    ubyte* pagetable;
+
+
+    void initialize(size_t npages)
+    {
+        size_t poolsize;
+
+        //debug(PRINTF) printf("Pool::Pool(%u)\n", npages);
+        poolsize = npages * PAGESIZE;
+        assert(poolsize >= POOLSIZE);
+        baseAddr = cast(byte *)os_mem_map(poolsize);
+
+        // Some of the code depends on page alignment of memory pools
+        assert((cast(size_t)baseAddr & (PAGESIZE - 1)) == 0);
+
+        if (!baseAddr)
+        {
+            //debug(PRINTF) printf("GC fail: poolsize = x%x, errno = %d\n", poolsize, errno);
+            //debug(PRINTF) printf("message = '%s'\n", sys_errlist[errno]);
+
+            npages = 0;
+            poolsize = 0;
+        }
+        //assert(baseAddr);
+        topAddr = baseAddr + poolsize;
+
+        mark.alloc(cast(size_t)poolsize / 16);
+        scan.alloc(cast(size_t)poolsize / 16);
+        freebits.alloc(cast(size_t)poolsize / 16);
+        noscan.alloc(cast(size_t)poolsize / 16);
+
+        pagetable = cast(ubyte*)cstdlib.malloc(npages);
+        if (!pagetable)
+            onOutOfMemoryError();
+        memset(pagetable, B_UNCOMMITTED, npages);
+
+        this.npages = npages;
+        ncommitted = 0;
+    }
+
+
+    void Dtor()
+    {
+        if (baseAddr)
+        {
+            int result;
+
+            if (ncommitted)
+            {
+                result = os_mem_decommit(baseAddr, 0, ncommitted * PAGESIZE);
+                assert(result == 0);
+                ncommitted = 0;
+            }
+
+            if (npages)
+            {
+                result = os_mem_unmap(baseAddr, npages * PAGESIZE);
+                assert(result == 0);
+                npages = 0;
+            }
+
+            baseAddr = null;
+            topAddr = null;
+        }
+        if (pagetable)
+            cstdlib.free(pagetable);
+
+        mark.Dtor();
+        scan.Dtor();
+        freebits.Dtor();
+        finals.Dtor();
+        noscan.Dtor();
+    }
+
+
+    void Invariant() { }
+
+
+    invariant()
+    {
+        //mark.Invariant();
+        //scan.Invariant();
+        //freebits.Invariant();
+        //finals.Invariant();
+        //noscan.Invariant();
+
+        if (baseAddr)
+        {
+            //if (baseAddr + npages * PAGESIZE != topAddr)
+                //printf("baseAddr = %p, npages = %d, topAddr = %p\n", baseAddr, npages, topAddr);
+            assert(baseAddr + npages * PAGESIZE == topAddr);
+            assert(ncommitted <= npages);
+        }
+
+        for (size_t i = 0; i < npages; i++)
+        {   Bins bin = cast(Bins)pagetable[i];
+
+            assert(bin < B_MAX);
+        }
+    }
+
+
+    /**
+     * Allocate n pages from Pool.
+     * Returns OPFAIL on failure.
+     */
+    size_t allocPages(size_t n)
+    {
+        size_t i;
+        size_t n2;
+
+        //debug(PRINTF) printf("Pool::allocPages(n = %d)\n", n);
+        n2 = n;
+        for (i = 0; i < ncommitted; i++)
+        {
+            if (pagetable[i] == B_FREE)
+            {
+                if (--n2 == 0)
+                {   //debug(PRINTF) printf("\texisting pn = %d\n", i - n + 1);
+                    return i - n + 1;
+                }
+            }
+            else
+                n2 = n;
+        }
+        return extendPages(n);
+    }
+
+    /**
+     * Extend Pool by n pages.
+     * Returns OPFAIL on failure.
+     */
+    size_t extendPages(size_t n)
+    {
+        //debug(PRINTF) printf("Pool::extendPages(n = %d)\n", n);
+        if (ncommitted + n <= npages)
+        {
+            size_t tocommit;
+
+            tocommit = (n + (COMMITSIZE/PAGESIZE) - 1) & ~(COMMITSIZE/PAGESIZE - 1);
+            if (ncommitted + tocommit > npages)
+                tocommit = npages - ncommitted;
+            //debug(PRINTF) printf("\tlooking to commit %d more pages\n", tocommit);
+            //fflush(stdout);
+            if (os_mem_commit(baseAddr, ncommitted * PAGESIZE, tocommit * PAGESIZE) == 0)
+            {
+                memset(pagetable + ncommitted, B_FREE, tocommit);
+                auto i = ncommitted;
+                ncommitted += tocommit;
+
+                while (i && pagetable[i - 1] == B_FREE)
+                    i--;
+
+                return i;
+            }
+            //debug(PRINTF) printf("\tfailed to commit %d pages\n", tocommit);
+        }
+
+        return OPFAIL;
+    }
+
+
+    /**
+     * Free npages pages starting with pagenum.
+     */
+    void freePages(size_t pagenum, size_t npages)
+    {
+        memset(&pagetable[pagenum], B_FREE, npages);
+    }
+
+
+    /**
+     * Used for sorting pooltable[]
+     */
+    int opCmp(Pool *p2)
+    {
+        if (baseAddr < p2.baseAddr)
+            return -1;
+        else
+        return cast(int)(baseAddr > p2.baseAddr);
+    }
+}
+
+
+/* ============================ SENTINEL =============================== */
+
+
+version (SENTINEL)
+{
+    const size_t SENTINEL_PRE = cast(size_t) 0xF4F4F4F4F4F4F4F4UL; // 32 or 64 bits
+    const ubyte SENTINEL_POST = 0xF5;           // 8 bits
+    const uint SENTINEL_EXTRA = 2 * size_t.sizeof + 1;
+
+
+    size_t* sentinel_size(void *p)  { return &(cast(size_t *)p)[-2]; }
+    size_t* sentinel_pre(void *p)   { return &(cast(size_t *)p)[-1]; }
+    ubyte* sentinel_post(void *p) { return &(cast(ubyte *)p)[*sentinel_size(p)]; }
+
+
+    void sentinel_init(void *p, size_t size)
+    {
+        *sentinel_size(p) = size;
+        *sentinel_pre(p) = SENTINEL_PRE;
+        *sentinel_post(p) = SENTINEL_POST;
+    }
+
+
+    void sentinel_Invariant(void *p)
+    {
+        assert(*sentinel_pre(p) == SENTINEL_PRE);
+        assert(*sentinel_post(p) == SENTINEL_POST);
+    }
+
+
+    void *sentinel_add(void *p)
+    {
+        return p + 2 * size_t.sizeof;
+    }
+
+
+    void *sentinel_sub(void *p)
+    {
+        return p - 2 * size_t.sizeof;
+    }
+}
+else
+{
+    const uint SENTINEL_EXTRA = 0;
+
+
+    void sentinel_init(void *p, size_t size)
+    {
+    }
+
+
+    void sentinel_Invariant(void *p)
+    {
+    }
+
+
+    void *sentinel_add(void *p)
+    {
+        return p;
+    }
+
+
+    void *sentinel_sub(void *p)
+    {
+        return p;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/gc/basic/posix.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,63 @@
+# Makefile to build the garbage collector D library for Posix
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR=../../../lib
+DOCDIR=../../../doc
+IMPDIR=../../../import
+LIBBASENAME=libdruntime-gc-basic.a
+MODULES=gc gcalloc gcbits gcstats gcx
+BUILDS=debug release unittest
+
+# Symbols
+
+DMD=dmd
+DOCFLAGS=-version=DDoc
+DFLAGS_release=-d -release -O -inline -w -nofloat
+DFLAGS_debug=-d -g -w -nofloat
+DFLAGS_unittest=$(DFLAGS_release) -unittest
+CFLAGS_release=-m32 -O
+CFLAGS_debug=-m32 -g
+CFLAGS_unittest=$(CFLAGS_release)
+
+# Derived symbols
+
+SRCS=$(addsuffix .d,$(MODULES))
+DOCS=
+IMPORTS=
+ALLLIBS=$(addsuffix /$(LIBBASENAME),$(addprefix $(LIBDIR)/,$(BUILDS)))
+
+# Patterns
+
+$(LIBDIR)/%/$(LIBBASENAME) : $(SRCS)
+	$(DMD) $(DFLAGS_$*) -lib -of$@ $^
+
+$(DOCDIR)/%.html : %.d
+	$(DMD) -c -d -o- -Df$@ $<
+
+$(IMPDIR)/%.di : %.d
+	$(DMD) -c -d -o- -Hf$@ $<
+
+# Rulez
+
+all : $(BUILDS) doc
+
+debug : $(LIBDIR)/debug/$(LIBBASENAME) $(IMPORTS)
+release : $(LIBDIR)/release/$(LIBBASENAME) $(IMPORTS)
+unittest : $(LIBDIR)/unittest/$(LIBBASENAME) $(IMPORTS)
+#doc : $(DOCS)
+
+clean :
+	rm -f $(IMPORTS) $(DOCS) $(ALLLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/gc/basic/win32.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,82 @@
+# Makefile to build the garbage collector D library for Posix
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR=..\..\..\lib
+DOCDIR=..\..\..\doc
+IMPDIR=..\..\..\import
+LIBBASENAME=druntime_gc_basic.lib
+#MODULES=gc gcalloc gcbits gcstats gcx
+BUILDS=debug release unittest
+
+# Symbols
+
+CC=dmc
+DMD=dmd
+DOCFLAGS=-version=DDoc
+DFLAGS_release=-d -release -O -inline -w -nofloat
+DFLAGS_debug=-d -g -w -nofloat
+DFLAGS_unittest=$(DFLAGS_release) -unittest
+CFLAGS_release=-mn -6 -r
+CFLAGS_debug=-g -mn -6 -r
+CFLAGS_unittest=$(CFLAGS_release)
+
+# Derived symbols
+
+SRCS=gc.d gcalloc.d gcbits.d gcstats.d gcx.d
+DOCS=
+IMPORTS=
+ALLLIBS=\
+	$(LIBDIR)\debug\$(LIBBASENAME) \
+	$(LIBDIR)\release\$(LIBBASENAME) \
+	$(LIBDIR)\unittest\$(LIBBASENAME)
+
+# Patterns
+
+#$(LIBDIR)\%\$(LIBBASENAME) : $(SRCS)
+#	$(DMD) $(DFLAGS_$*) -lib -of$@ $^
+
+#$(DOCDIR)\%.html : %.d
+#	$(DMD) -c -d -o- -Df$@ $<
+
+#$(IMPDIR)\%.di : %.d
+#	$(DMD) -c -d -o- -Hf$@ $<
+
+# Patterns - debug
+
+$(LIBDIR)\debug\$(LIBBASENAME) : $(SRCS)
+	$(DMD) $(DFLAGS_debug) -lib -of$@ $**
+
+# Patterns - release
+
+$(LIBDIR)\release\$(LIBBASENAME) : $(SRCS)
+	$(DMD) $(DFLAGS_release) -lib -of$@ $**
+
+# Patterns - unittest
+
+$(LIBDIR)\unittest\$(LIBBASENAME) : $(SRCS)
+	$(DMD) $(DFLAGS_unittest) -lib -of$@ $**
+
+# Rulez
+
+all : $(BUILDS) doc
+
+debug : $(LIBDIR)\debug\$(LIBBASENAME) $(IMPORTS)
+release : $(LIBDIR)\release\$(LIBBASENAME) $(IMPORTS)
+unittest : $(LIBDIR)\unittest\$(LIBBASENAME) $(IMPORTS)
+#doc : $(DOCS)
+
+clean :
+	del $(IMPORTS) $(DOCS) $(ALLLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/gc/stub/gc.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,359 @@
+/**
+ * This module contains a minimal garbage collector implementation according to
+ * published requirements.  This library is mostly intended to serve as an
+ * example, but it is usable in applications which do not rely on a garbage
+ * collector to clean up memory (ie. when dynamic array resizing is not used,
+ * and all memory allocated with 'new' is freed deterministically with
+ * 'delete').
+ *
+ * Please note that block attribute data must be tracked, or at a minimum, the
+ * FINALIZE bit must be tracked for any allocated memory block because calling
+ * rt_finalize on a non-object block can result in an access violation.  In the
+ * allocator below, this tracking is done via a leading uint bitmask.  A real
+ * allocator may do better to store this data separately, similar to the basic
+ * GC.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module gc.gc;
+
+private
+{
+   import core.stdc.stdlib;
+
+   enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001,
+        NO_SCAN  = 0b0000_0010,
+        NO_MOVE  = 0b0000_0100,
+        ALL_BITS = 0b1111_1111
+    }
+
+    struct BlkInfo
+    {
+        void*  base;
+        size_t size;
+        uint   attr;
+    }
+
+    extern (C) void thread_init();
+    extern (C) void onOutOfMemoryError();
+
+    struct Proxy
+    {
+        extern (C) void function() gc_enable;
+        extern (C) void function() gc_disable;
+        extern (C) void function() gc_collect;
+        extern (C) void function() gc_minimize;
+
+        extern (C) uint function(void*) gc_getAttr;
+        extern (C) uint function(void*, uint) gc_setAttr;
+        extern (C) uint function(void*, uint) gc_clrAttr;
+
+        extern (C) void*  function(size_t, uint) gc_malloc;
+        extern (C) void*  function(size_t, uint) gc_calloc;
+        extern (C) void*  function(void*, size_t, uint ba) gc_realloc;
+        extern (C) size_t function(void*, size_t, size_t) gc_extend;
+        extern (C) size_t function(size_t) gc_reserve;
+        extern (C) void   function(void*) gc_free;
+
+        extern (C) void*   function(void*) gc_addrOf;
+        extern (C) size_t  function(void*) gc_sizeOf;
+
+        extern (C) BlkInfo function(void*) gc_query;
+
+        extern (C) void function(void*) gc_addRoot;
+        extern (C) void function(void*, size_t) gc_addRange;
+
+        extern (C) void function(void*) gc_removeRoot;
+        extern (C) void function(void*) gc_removeRange;
+    }
+
+    __gshared Proxy  pthis;
+    __gshared Proxy* proxy;
+
+    void initProxy()
+    {
+        pthis.gc_enable = &gc_enable;
+        pthis.gc_disable = &gc_disable;
+        pthis.gc_collect = &gc_collect;
+        pthis.gc_minimize = &gc_minimize;
+
+        pthis.gc_getAttr = &gc_getAttr;
+        pthis.gc_setAttr = &gc_setAttr;
+        pthis.gc_clrAttr = &gc_clrAttr;
+
+        pthis.gc_malloc = &gc_malloc;
+        pthis.gc_calloc = &gc_calloc;
+        pthis.gc_realloc = &gc_realloc;
+        pthis.gc_extend = &gc_extend;
+        pthis.gc_reserve = &gc_reserve;
+        pthis.gc_free = &gc_free;
+
+        pthis.gc_addrOf = &gc_addrOf;
+        pthis.gc_sizeOf = &gc_sizeOf;
+
+        pthis.gc_query = &gc_query;
+
+        pthis.gc_addRoot = &gc_addRoot;
+        pthis.gc_addRange = &gc_addRange;
+
+        pthis.gc_removeRoot = &gc_removeRoot;
+        pthis.gc_removeRange = &gc_removeRange;
+    }
+
+    __gshared void** roots  = null;
+    __gshared size_t nroots = 0;
+
+    struct Range
+    {
+        void*  pos;
+        size_t len;
+    }
+
+    __gshared Range* ranges  = null;
+    __gshared size_t nranges = 0;
+}
+
+extern (C) void gc_init()
+{
+    // NOTE: The GC must initialize the thread library before its first
+    //       collection, and always before returning from gc_init().
+    thread_init();
+    initProxy();
+}
+
+extern (C) void gc_term()
+{
+    free( roots );
+    free( ranges );
+}
+
+extern (C) void gc_enable()
+{
+    if( proxy is null )
+        return;
+    return proxy.gc_enable();
+}
+
+extern (C) void gc_disable()
+{
+    if( proxy is null )
+        return;
+    return proxy.gc_disable();
+}
+
+extern (C) void gc_collect()
+{
+    if( proxy is null )
+        return;
+    return proxy.gc_collect();
+}
+
+extern (C) void gc_minimize()
+{
+    if( proxy is null )
+        return;
+    return proxy.gc_minimize();
+}
+
+extern (C) uint gc_getAttr( void* p )
+{
+    if( proxy is null )
+        return 0;
+    return proxy.gc_getAttr( p );
+}
+
+extern (C) uint gc_setAttr( void* p, uint a )
+{
+    if( proxy is null )
+        return 0;
+    return proxy.gc_setAttr( p, a );
+}
+
+extern (C) uint gc_clrAttr( void* p, uint a )
+{
+    if( proxy is null )
+        return 0;
+    return proxy.gc_clrAttr( p, a );
+}
+
+extern (C) void* gc_malloc( size_t sz, uint ba = 0 )
+{
+    if( proxy is null )
+    {
+        void* p = malloc( sz );
+
+        if( sz && p is null )
+            onOutOfMemoryError();
+        return p;
+    }
+    return proxy.gc_malloc( sz, ba );
+}
+
+extern (C) void* gc_calloc( size_t sz, uint ba = 0 )
+{
+    if( proxy is null )
+    {
+        void* p = calloc( 1, sz );
+
+        if( sz && p is null )
+            onOutOfMemoryError();
+        return p;
+    }
+    return proxy.gc_calloc( sz, ba );
+}
+
+extern (C) void* gc_realloc( void* p, size_t sz, uint ba = 0 )
+{
+    if( proxy is null )
+    {
+        p = realloc( p, sz );
+
+        if( sz && p is null )
+            onOutOfMemoryError();
+        return p;
+    }
+    return proxy.gc_realloc( p, sz, ba );
+}
+
+extern (C) size_t gc_extend( void* p, size_t mx, size_t sz )
+{
+    if( proxy is null )
+        return 0;
+    return proxy.gc_extend( p, mx, sz );
+}
+
+extern (C) size_t gc_reserve( size_t sz )
+{
+    if( proxy is null )
+        return 0;
+    return proxy.gc_reserve( sz );
+}
+
+extern (C) void gc_free( void* p )
+{
+    if( proxy is null )
+        return free( p );
+    return proxy.gc_free( p );
+}
+
+extern (C) void* gc_addrOf( void* p )
+{
+    if( proxy is null )
+        return null;
+    return proxy.gc_addrOf( p );
+}
+
+extern (C) size_t gc_sizeOf( void* p )
+{
+    if( proxy is null )
+        return 0;
+    return proxy.gc_sizeOf( p );
+}
+
+extern (C) BlkInfo gc_query( void* p )
+{
+    if( proxy is null )
+        return BlkInfo.init;
+    return proxy.gc_query( p );
+}
+
+extern (C) void gc_addRoot( void* p )
+{
+    if( proxy is null )
+    {
+        void** r = cast(void**) realloc( roots,
+                                         (nroots+1) * roots[0].sizeof );
+        if( r is null )
+            onOutOfMemoryError();
+        r[nroots++] = p;
+        roots = r;
+
+    }
+    return proxy.gc_addRoot( p );
+}
+
+extern (C) void gc_addRange( void* p, size_t sz )
+{
+    if( proxy is null )
+    {
+        Range* r = cast(Range*) realloc( ranges,
+                                         (nranges+1) * ranges[0].sizeof );
+        if( r is null )
+            onOutOfMemoryError();
+        r[nranges].pos = p;
+        r[nranges].len = sz;
+        ranges = r;
+        ++nranges;
+    }
+    return proxy.gc_addRange( p, sz );
+}
+
+extern (C) void gc_removeRoot( void *p )
+{
+    if( proxy is null )
+    {
+        for( size_t i = 0; i < nroots; ++i )
+        {
+            if( roots[i] is p )
+            {
+                roots[i] = roots[--nroots];
+                return;
+            }
+        }
+        assert( false );
+    }
+    return proxy.gc_removeRoot( p );
+}
+
+extern (C) void gc_removeRange( void *p )
+{
+    if( proxy is null )
+    {
+        for( size_t i = 0; i < nranges; ++i )
+        {
+            if( ranges[i].pos is p )
+            {
+                ranges[i] = ranges[--nranges];
+                return;
+            }
+        }
+        assert( false );
+    }
+    return proxy.gc_removeRange( p );
+}
+
+extern (C) Proxy* gc_getProxy()
+{
+    return &pthis;
+}
+
+export extern (C) void gc_setProxy( Proxy* p )
+{
+    if( proxy !is null )
+    {
+        // TODO: Decide if this is an error condition.
+    }
+    proxy = p;
+    foreach( r; roots[0 .. nroots] )
+        proxy.gc_addRoot( r );
+    foreach( r; ranges[0 .. nranges] )
+        proxy.gc_addRange( r.pos, r.len );
+}
+
+export extern (C) void gc_clrProxy()
+{
+    foreach( r; ranges[0 .. nranges] )
+        proxy.gc_removeRange( r.pos );
+    foreach( r; roots[0 .. nroots] )
+        proxy.gc_removeRoot( r );
+    proxy = null;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/gc/stub/posix.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,63 @@
+# Makefile to build the garbage collector D library for Posix
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR=../../../lib
+DOCDIR=../../../doc
+IMPDIR=../../../import
+LIBBASENAME=libdruntime-gc-stub.a
+MODULES=gc
+BUILDS=debug release unittest
+
+# Symbols
+
+DMD=dmd
+DOCFLAGS=-version=DDoc
+DFLAGS_release=-d -release -O -inline -w -nofloat
+DFLAGS_debug=-d -g -w -nofloat
+DFLAGS_unittest=$(DFLAGS_release) -unittest
+CFLAGS_release=-m32 -O
+CFLAGS_debug=-m32 -g
+CFLAGS_unittest=$(CFLAGS_release)
+
+# Derived symbols
+
+SRCS=$(addsuffix .d,$(MODULES))
+DOCS=
+IMPORTS=
+ALLLIBS=$(addsuffix /$(LIBBASENAME),$(addprefix $(LIBDIR)/,$(BUILDS)))
+
+# Patterns
+
+$(LIBDIR)/%/$(LIBBASENAME) : $(SRCS)
+	$(DMD) $(DFLAGS_$*) -lib -of$@ $^
+
+$(DOCDIR)/%.html : %.d
+	$(DMD) -c -d -o- -Df$@ $<
+
+$(IMPDIR)/%.di : %.d
+	$(DMD) -c -d -o- -Hf$@ $<
+
+# Rulez
+
+all : $(BUILDS) doc
+
+debug : $(LIBDIR)/debug/$(LIBBASENAME) $(IMPORTS)
+release : $(LIBDIR)/release/$(LIBBASENAME) $(IMPORTS)
+unittest : $(LIBDIR)/unittest/$(LIBBASENAME) $(IMPORTS)
+#doc : $(DOCS)
+
+clean :
+	rm -f $(IMPORTS) $(DOCS) $(ALLLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/gc/stub/win32.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,82 @@
+# Makefile to build the garbage collector D library for Posix
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR=..\..\..\lib
+DOCDIR=..\..\..\doc
+IMPDIR=..\..\..\import
+LIBBASENAME=druntime_gc_stub.lib
+#MODULES=gc
+BUILDS=debug release unittest
+
+# Symbols
+
+CC=dmc
+DMD=dmd
+DOCFLAGS=-version=DDoc
+DFLAGS_release=-d -release -O -inline -w -nofloat
+DFLAGS_debug=-d -g -w -nofloat
+DFLAGS_unittest=$(DFLAGS_release) -unittest
+CFLAGS_release=-mn -6 -r
+CFLAGS_debug=-g -mn -6 -r
+CFLAGS_unittest=$(CFLAGS_release)
+
+# Derived symbols
+
+SRCS=gc.d
+DOCS=
+IMPORTS=
+ALLLIBS=\
+	$(LIBDIR)\debug\$(LIBBASENAME) \
+	$(LIBDIR)\release\$(LIBBASENAME) \
+	$(LIBDIR)\unittest\$(LIBBASENAME)
+
+# Patterns
+
+#$(LIBDIR)\%\$(LIBBASENAME) : $(SRCS)
+#	$(DMD) $(DFLAGS_$*) -lib -of$@ $^
+
+#$(DOCDIR)\%.html : %.d
+#	$(DMD) -c -d -o- -Df$@ $<
+
+#$(IMPDIR)\%.di : %.d
+#	$(DMD) -c -d -o- -Hf$@ $<
+
+# Patterns - debug
+
+$(LIBDIR)\debug\$(LIBBASENAME) : $(SRCS)
+	$(DMD) $(DFLAGS_debug) -lib -of$@ $**
+
+# Patterns - release
+
+$(LIBDIR)\release\$(LIBBASENAME) : $(SRCS)
+	$(DMD) $(DFLAGS_release) -lib -of$@ $**
+
+# Patterns - unittest
+
+$(LIBDIR)\unittest\$(LIBBASENAME) : $(SRCS)
+	$(DMD) $(DFLAGS_unittest) -lib -of$@ $**
+
+# Rulez
+
+all : $(BUILDS) doc
+
+debug : $(LIBDIR)\debug\$(LIBBASENAME) $(IMPORTS)
+release : $(LIBDIR)\release\$(LIBBASENAME) $(IMPORTS)
+unittest : $(LIBDIR)\unittest\$(LIBBASENAME) $(IMPORTS)
+#doc : $(DOCS)
+
+clean :
+	del $(IMPORTS) $(DOCS) $(ALLLIBS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/ldc-posix-tango.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,123 @@
+# Makefile to build the composite D runtime library for Linux
+# Designed to work with GNU make
+# Targets:
+#	make
+#		same as make lib
+#	make all
+#		make lib-release lib-debug and doc
+#	make lib
+#		Build the compiler runtime library (which version depends on VERSION, name on LIB_BUILD)
+#	make lib-release
+#		Build the release version of the compiler runtime library
+#	make lib-debug
+#		Build the debug version of the compiler runtime library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete unneeded files created by build process
+#	make clean-all
+#		Delete unneeded files created by build process and the libraries
+#	make unittest
+#		Performs the unittests of the runtime library
+
+ifeq ($(SHARED),yes)
+LIB_EXT=so
+LC_CMD=$(CC) -shared -o
+else
+LIB_EXT=a
+LC_CMD=$(CLC)
+endif
+
+LIB_BASE=libtango-base-ldc
+LIB_BUILD=
+LIB_TARGET=$(LIB_BASE)$(LIB_BUILD).$(LIB_EXT)
+LIB_BC=$(LIB_BASE)$(LIB_BUILD)-bc.a
+LIB_C=$(LIB_BASE)$(LIB_BUILD)-c.a
+LIB_MASK=$(LIB_BASE)*.a $(LIB_BASE)*.so
+
+DIR_CC=./common/tango
+DIR_RT=./compiler/ldc
+DIR_RT2=./compiler/shared
+DIR_GC=./gc/basic
+MAKEFILE=ldc-posix.mak
+targets : libs
+all     : lib-release lib-debug doc
+
+include ldcCommonFlags.mak
+
+.PHONY : libs lib-release lib-debug unittest all doc clean install clean-all targets
+
+######################################################
+
+ALL_OBJS=
+
+######################################################
+
+ALL_DOCS=
+
+libs : $(LIB_TARGET) $(LIB_BC) $(LIB_C)
+$(LIB_TARGET) : $(ALL_OBJS)
+	$(MAKE) -C $(DIR_CC) -fldc.mak libs DC=$(DC) ADD_DFLAGS="$(ADD_DFLAGS)" ADD_CFLAGS="$(ADD_CFLAGS)" \
+	 	VERSION="$(VERSION)" LIB_BUILD="$(LIB_BUILD)" SHARED="$(SHARED)"
+	$(MAKE) -C $(DIR_RT) -fldc.mak libs DC=$(DC) ADD_DFLAGS="$(ADD_DFLAGS)" ADD_CFLAGS="$(ADD_CFLAGS)" \
+	 	VERSION="$(VERSION)" LIB_BUILD="$(LIB_BUILD)" SHARED="$(SHARED)"
+	$(MAKE) -C $(DIR_GC) -fldc.mak libs DC=$(DC) ADD_DFLAGS="$(ADD_DFLAGS)" ADD_CFLAGS="$(ADD_CFLAGS)" \
+                VERSION="$(VERSION)" LIB_BUILD="$(LIB_BUILD)" SHARED="$(SHARED)"
+	$(RM) $@
+	$(LC_CMD) $@ `find $(DIR_CC) -name "*.o" | xargs echo`
+	$(LC_CMD) $@ `find $(DIR_RT) -name "*.o" | xargs echo`
+	$(LC_CMD) $@ `find $(DIR_RT2) -name "*.o" | xargs echo`
+	$(LC_CMD) $@ `find $(DIR_GC) -name "*.o" | xargs echo`
+ifneq ($(RANLIB),)
+	$(RANLIB) $@
+endif
+
+$(LIB_BC): $(LIB_TARGET)
+	$(RM) $@
+	$(LC) $@ `find $(DIR_CC) -name "*.bc" | xargs echo`
+	$(LC) $@ `find $(DIR_RT) -name "*.bc" | xargs echo`
+	$(LC) $@ `find $(DIR_RT2) -name "*.bc" | xargs echo`
+	$(LC) $@ `find $(DIR_GC) -name "*.bc" | xargs echo`
+ifneq ($(RANLIB),)
+	$(RANLIB) $@
+endif
+
+LIB_C_OBJS= $(DIR_CC)/libtango-cc-tango-c-only$(LIB_BUILD).a $(DIR_RT)/libtango-rt-ldc$(LIB_BUILD)-c.a 
+
+$(LIB_C): $(LIB_TARGET) $(LIB_C_OBJS)
+	$(CLC) $@ $(LIB_C_OBJS)
+
+doc : $(ALL_DOCS)
+	$(MAKE) -C $(DIR_CC) -fldc.mak doc DC=$(DC)
+	$(MAKE) -C $(DIR_RT) -fldc.mak doc DC=$(DC)
+	$(MAKE) -C $(DIR_GC) -fldc.mak doc DC=$(DC)
+
+######################################################
+
+#	find . -name "*.di" | xargs $(RM)
+clean :
+	$(RM) $(ALL_OBJS)
+	$(MAKE) -C $(DIR_CC) -fldc.mak clean
+	$(MAKE) -C $(DIR_RT) -fldc.mak clean
+	$(MAKE) -C $(DIR_GC) -fldc.mak clean
+
+clean-all : clean
+	$(MAKE) -C $(DIR_CC) -fldc.mak clean-all
+	$(MAKE) -C $(DIR_RT) -fldc.mak clean-all
+	$(MAKE) -C $(DIR_GC) -fldc.mak clean-all
+	$(RM) $(ALL_DOCS)
+	$(RM) $(LIB_MASK)
+	find $(DIR_CC) -name "*.bc" | xargs rm -rf
+	find $(DIR_RT) -name "*.bc" | xargs rm -rf
+	find $(DIR_RT2) -name "*.bc"| xargs rm -rf
+	find $(DIR_GC) -name "*.bc" | xargs rm -rf
+	find $(DIR_CC) -name "*.o"  | xargs rm -rf
+	find $(DIR_RT) -name "*.o"  | xargs rm -rf
+	find $(DIR_RT2) -name "*.o" | xargs rm -rf
+	find $(DIR_GC) -name "*.o"  | xargs rm -rf
+
+install :
+	$(MAKE) -C $(DIR_CC) -fldc.mak install
+	$(MAKE) -C $(DIR_RT) -fldc.mak install
+	$(MAKE) -C $(DIR_GC) -fldc.mak install
+#	$(CP) $(LIB_MASK) $(LIB_DEST)/.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/ldc-posix.mak	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,80 @@
+# Makefile to build the composite D runtime library for Linux
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make debug
+#		Build the debug version of the library
+#   make release
+#       Build the release version of the library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete all files created by build process
+
+# Essentials
+
+LIBDIR:=../lib
+DOCDIR:=../doc
+LIBBASENAME=libdruntime.a
+
+DIR_CC=common
+DIR_RT=compiler/ldc
+DIR_GC=gc/stub
+
+# Symbols
+
+DMD="ldc2 -vv"
+CLC=ar rsv
+
+# Targets
+
+all : debug release doc unittest $(LIBDIR)/$(LIBBASENAME)
+
+# unittest :
+# 	$(MAKE) -fdmd-posix.mak lib MAKE_LIB="unittest"
+# 	dmd -unittest unittest ../import/core/stdc/stdarg \
+# 		-defaultlib="$(DUP_TARGET)" -debuglib="$(DUP_TARGET)"
+# 	$(RM) stdarg.o
+# 	./unittest
+
+debug release unittest :
+	@$(MAKE) DMD=$(DMD) -C $(DIR_CC) -fposix.mak $@
+	@$(MAKE) DMD=$(DMD) -C $(DIR_RT) -fposix.mak $@
+	@$(MAKE) DMD=$(DMD) -C $(DIR_GC) -fposix.mak $@
+ifeq ($(DMD),ldc2 -vv)
+	@$(CLC) $(LIBDIR)/$@/$(LIBBASENAME) \
+		$(LIBDIR)/$@/libdruntime-core.a \
+		$(LIBDIR)/$@/libdruntime-rt-ldc.a \
+		$(LIBDIR)/$@/libdruntime-gc-stub.a
+else
+	@$(DMD) -lib -of$(LIBDIR)/$@/$(LIBBASENAME) \
+		$(LIBDIR)/$@/libdruntime-core.a \
+		$(LIBDIR)/$@/libdruntime-rt-dmd.a \
+		$(LIBDIR)/$@/libdruntime-gc-basic.a
+endif
+
+$(LIBDIR)/$(LIBBASENAME) : $(LIBDIR)/release/$(LIBBASENAME)
+	ln -sf $(realpath $<) $@
+
+doc : $(ALL_DOCS)
+	$(MAKE) DMD=$(DMD) -C $(DIR_CC) --no-print-directory -fposix.mak doc
+#	$(MAKE) DMD=$(DMD) -C $(DIR_RT) --no-print-directory -fposix.mak doc
+#	$(MAKE) DMD=$(DMD) -C $(DIR_GC) --no-print-directory -fposix.mak doc
+
+######################################################
+
+clean :
+	$(MAKE) DMD=$(DMD) -C $(DIR_CC) -fposix.mak clean
+	$(MAKE) DMD=$(DMD) -C $(DIR_RT) -fposix.mak clean
+	$(MAKE) DMD=$(DMD) -C $(DIR_GC) -fposix.mak clean
+#find . -name "*.di" | xargs $(RM)
+	rm -rf $(LIBDIR) $(DOCDIR)
+
+# install :
+# 	make -C $(DIR_CC) --no-print-directory -fposix.mak install
+# 	make -C $(DIR_RT) --no-print-directory -fposix.mak install
+# 	make -C $(DIR_GC) --no-print-directory -fposix.mak install
+# 	$(CP) $(LIB_MASK) $(LIB_DEST)/.
+# 	$(CP) $(DUP_MASK) $(LIB_DEST)/.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/sc.ini	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,7 @@
+[Version]
+version=7.51 Build 020
+
+[Environment]
+LIB=%@P%\..\lib;\dm\lib
+DFLAGS="-I%HOME%\common" "-I%HOME%\..\import"
+LINKCMD=%@P%\..\..\dm\bin\link.exe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/test-dmd.sh	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+OLDHOME=$HOME
+export HOME=`pwd`
+
+goerror(){
+    export HOME=$OLDHOME
+    echo "="
+    echo "= *** Error ***"
+    echo "="
+    exit 1
+}
+
+make unittest -fdmd-posix.mak   || goerror
+
+export HOME=$OLDHOME