diff --git a/arch/nt32/atomic.h b/arch/nt32/atomic.h
new file mode 100644
index 0000000..d7d9365
--- /dev/null
+++ b/arch/nt32/atomic.h
@@ -0,0 +1,7 @@
+#ifndef _INTERNAL_ATOMIC_NT64_H
+#define _INTERNAL_ATOMIC_NT64_H
+
+#include "../i386/atomic.h"
+
+#endif
+
diff --git a/arch/nt32/psxglue.h b/arch/nt32/psxglue.h
new file mode 100644
index 0000000..73ad2b0
--- /dev/null
+++ b/arch/nt32/psxglue.h
@@ -0,0 +1,63 @@
+#ifndef _PSXGLUE_H_
+#define _PSXGLUE_H_
+
+#define __PSXOPT_NATIVE		0x0
+#define __PSXOPT_POSIX		0x1
+#define __PSXOPT_TTYDBG		0x2
+#define __PSXOPT_LDSO		0x4
+
+typedef int	__ldso_dladdr(const void * addr, void * info);
+typedef int	__ldso_dlinfo(void * dso, int req, void * res);
+typedef void *	__ldso_dlsym(void * p, const char * s, void * ra);
+typedef void *	__ldso_dlopen(const char * file, int mode);
+typedef int	__ldso_dlclose(void *p);
+typedef char *	__ldso_dlerror(void);
+typedef void	__ldso_reset_tls(void);
+
+typedef void	__psx_convert_thread(void);
+typedef void	__psx_unmapself(void *, void *);
+typedef void *	__psx_get_osfhandle(int fd);
+
+struct __ldso_vtbl {
+	__ldso_dladdr *		dladdr;
+	__ldso_dlinfo *		dlinfo;
+	__ldso_dlsym *		dlsym;
+	__ldso_dlopen *		dlopen;
+	__ldso_dlclose *	dlclose;
+	__ldso_dlerror *	dlerror;
+	__ldso_reset_tls *	reset_tls;
+};
+
+struct __psx_vtbl {
+	__psx_convert_thread *	convert_thread;
+	__psx_unmapself *	unmapself;
+	__psx_get_osfhandle *	get_osfhandle;
+};
+
+struct __psx_context {
+	int			size;
+	int			options;
+	void ***		sys_vtbl;
+	struct __ldso_vtbl *	ldso_vtbl;
+	struct __psx_vtbl *	psx_vtbl;
+	unsigned int		teb_sys_idx;
+	unsigned int		teb_libc_idx;
+	void *			pthread_surrogate_fn;
+	void *			pthread_create_fn;
+};
+
+struct __tlca {
+	void *	pthread_self;
+	int *	pthread_set_child_tid;
+	int *	pthread_clear_child_tid;
+	char *	pthread_tls;
+	char ***pthread_dtls;
+};
+
+typedef int __psx_init_routine(
+	int *			argc,
+	char ***		argv,
+	char ***		envp,
+	struct __psx_context *	ctx);
+
+#endif
diff --git a/arch/nt32/pthread_arch.h b/arch/nt32/pthread_arch.h
new file mode 100644
index 0000000..d5f2553
--- /dev/null
+++ b/arch/nt32/pthread_arch.h
@@ -0,0 +1,74 @@
+#include <stddef.h>
+
+#define	TP_ADJ(p)	(p)
+#define	CANCEL_REG_IP	16
+
+extern uintptr_t __teb_sys_idx;
+extern uintptr_t __teb_libc_idx;
+
+struct __os_tib {
+	void *	exception_list;
+	void *	stack_base;
+	void *	stack_limit;
+};
+
+static __inline__ void * __os_get_teb_address(void)
+{
+	void * ptrRet;
+	__asm__ __volatile__ (
+		"mov %%fs:0x18, %0\n\t"
+		: "=r" (ptrRet) : :
+		);
+	return ptrRet;
+}
+
+
+static inline void __pthread_convert(void)
+{
+	/* (third-party thread support) */
+	__asm__ __volatile__ (
+		"push %eax\n\t"
+		"mov  ___psx_vtbl,%eax\n\t"
+		"call *(%eax)\n\t"
+		"pop  %eax\n\t"
+		);
+}
+
+
+static inline struct pthread ** __psx_tlca(void)
+{
+	struct pthread **	ptlca;
+	struct __os_tib *	tib;
+	void **			slots;
+	void ***		xslots;
+	uintptr_t		sys_idx;
+
+	tib = __os_get_teb_address();
+	sys_idx = __teb_sys_idx;
+
+	if (sys_idx < 64) {
+		slots = (void **)((uintptr_t)tib + 0xa40);
+		ptlca = (struct pthread **)(slots[sys_idx]);
+	} else {
+		xslots = (void ***)((uintptr_t)tib + 0xbc0);
+		slots  = *xslots;
+		ptlca = (struct pthread **)(slots[sys_idx - 64]);
+	}
+
+	return ptlca;
+}
+
+
+static inline struct pthread * __pthread_self(void)
+{
+	struct pthread ** ptlca;
+
+	ptlca = __psx_tlca();
+	if (ptlca) return *ptlca;
+
+	/* (third-party thread) */
+	__pthread_convert();
+	ptlca = __psx_tlca();
+	return *ptlca;
+}
+
diff --git a/arch/nt32/reloc.h b/arch/nt32/reloc.h
new file mode 100644
index 0000000..20abf44
--- /dev/null
+++ b/arch/nt32/reloc.h
@@ -0,0 +1,6 @@
+#define LDSO_ARCH "PE32+"
+
+static int remap_rel(int type)
+{
+	return 0;
+}
diff --git a/arch/nt32/src/crt_glue.c b/arch/nt32/src/crt_glue.c
new file mode 100644
index 0000000..abfd1fe
--- /dev/null
+++ b/arch/nt32/src/crt_glue.c
@@ -0,0 +1,87 @@
+#include <unistd.h>
+#include <pthread.h>
+#include "atomic.h"
+#include "syscall.h"
+#include "psxglue.h"
+#include "pthread_impl.h"
+
+extern struct __ldso_vtbl *	__ldso_vtbl;
+extern struct __psx_vtbl *	__psx_vtbl;
+
+typedef int __app_main();
+typedef int __pthread_surrogate_routine(struct pthread *);
+
+extern int _init(void);
+static int __pthread_surrogate_init(struct pthread * self);
+
+extern int __libc_start_main(
+	void *	main,
+	int	argc,
+	char **	argv);
+
+void __libc_entry_routine(
+	__app_main *		__main,
+	__psx_init_routine *	__psx_init,
+	int			options)
+{
+	int			argc;
+	char **			argv;
+	char **			envp;
+	struct __psx_context	ctx;
+
+	/* ctx init */
+	ctx.size		= sizeof(ctx);
+	ctx.options		= options;
+	ctx.pthread_create_fn	= pthread_create;
+	ctx.pthread_surrogate_fn= __pthread_surrogate_init;
+
+	/* __psx_init must succeed... */
+	if (__psx_init(&argc,&argv,&envp,&ctx))
+		a_crash();
+
+	/* ...and conform */
+	else if (envp != argv + (argc + 1))
+		a_crash();
+
+	/* dso init routines */
+	_init();
+
+	/* write once */
+	__syscall_vtbl	= (unsigned long **)ctx.sys_vtbl;
+	__ldso_vtbl	= ctx.ldso_vtbl;
+	__psx_vtbl	= ctx.psx_vtbl;
+	__teb_sys_idx	= ctx.teb_sys_idx;
+	__teb_libc_idx	= ctx.teb_libc_idx;
+
+	/* enter libc */
+	__libc_start_main(__main,argc,argv);
+
+	/* guard */
+	a_crash();
+}
+
+static int __pthread_surrogate_init(struct pthread * self)
+{
+	/**
+	 * invoked by psxscl upon creation of a surrogate libc
+	 * thread, which in turn may only call pthread_create();
+	 *
+	 * the purpose of this mecahnism is to support a scenario
+	 * where a third-party library creates a non-posix thread
+	 * which then calls, be it directly or via a callback
+	 * function, a libc api that depends on a valid
+	 * pthread_self.
+	 *
+	 * self: a pointer to an already zero'ed memory page
+	 *
+	 * struct pthread relevant members:
+	 * --------------------------------
+	 * cancel (already zero)
+	 * canary (already zero)
+	 *
+	 * pthread_create() reference:
+	 * 1a47ed15eebf96d0c8d5de4aea54108bc8cc3f53
+	**/
+
+	return 0;
+}
diff --git a/arch/nt32/src/crt_pe.c b/arch/nt32/src/crt_pe.c
new file mode 100644
index 0000000..0dc75a4
--- /dev/null
+++ b/arch/nt32/src/crt_pe.c
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+#include <threads.h>
+
+void * __pthread_getspecific_impl(pthread_key_t k)
+{
+	return (__pthread_self())->tsd[k];
+}
diff --git a/arch/nt32/src/crt_tls.c b/arch/nt32/src/crt_tls.c
new file mode 100644
index 0000000..15183d3
--- /dev/null
+++ b/arch/nt32/src/crt_tls.c
@@ -0,0 +1,27 @@
+#include <stdint.h>
+#include <stddef.h>
+#include "psxglue.h"
+#include "pthread_arch.h"
+
+typedef unsigned int __tls_word	__attribute__((mode(word)));
+typedef unsigned int __tls_ptr	__attribute__((mode(pointer)));
+
+struct __emutls_object
+{
+	__tls_word	size;
+	__tls_word	align;
+	ptrdiff_t	offset;
+	void *		defval;
+};
+
+void * __emutls_get_address (struct __emutls_object * obj)
+{
+	int dsoidx = obj->align & 0xFFFF0000;
+	struct __tlca * tlca = (struct __tlca *)__psx_tlca();
+
+	if (dsoidx)
+		return (*tlca->pthread_dtls)[dsoidx >> 16] + obj->offset;
+	else
+		return tlca->pthread_tls + obj->offset;
+}
+
diff --git a/arch/nt32/src/libc_entry_point.c b/arch/nt32/src/libc_entry_point.c
new file mode 100644
index 0000000..0929cc4
--- /dev/null
+++ b/arch/nt32/src/libc_entry_point.c
@@ -0,0 +1,10 @@
+typedef unsigned int uint32_t;
+
+int __libc_entry_point(
+	void *		hinstance,
+	uint32_t	reason,
+	void *		reserved)
+{
+	return 1;
+}
+
diff --git a/arch/nt32/src/syscall_disp.c b/arch/nt32/src/syscall_disp.c
new file mode 100644
index 0000000..3369ca0
--- /dev/null
+++ b/arch/nt32/src/syscall_disp.c
@@ -0,0 +1,22 @@
+#include <stdint.h>
+#include <stddef.h>
+#include "syscall.h"
+#include "psxglue.h"
+
+extern struct __psx_vtbl * __psx_vtbl;
+
+void __unmapself(void * base, size_t size)
+{
+	__psx_vtbl->unmapself(base,(void *)size);
+}
+
+uintptr_t __syscall_disp(long n,
+		uintptr_t a1,
+		uintptr_t a2,
+		uintptr_t a3,
+		uintptr_t a4,
+		uintptr_t a5,
+		uintptr_t a6)
+{
+	return __syscall(n,a1,a2,a3,a4,a5,a6);
+}
diff --git a/arch/nt32/src/vtbl.c b/arch/nt32/src/vtbl.c
new file mode 100644
index 0000000..7e9c0e8
--- /dev/null
+++ b/arch/nt32/src/vtbl.c
@@ -0,0 +1,12 @@
+#include "psxglue.h"
+
+unsigned long **	__syscall_vtbl	= 0;
+struct __ldso_vtbl *	__ldso_vtbl	= 0;
+struct __psx_vtbl *	__psx_vtbl	= 0;
+unsigned long		__teb_sys_idx	= 0;
+unsigned long		__teb_libc_idx	= 0;
+
+void __chkstk_ms(void)
+{
+}
+
diff --git a/arch/nt32/syscall_arch.h b/arch/nt32/syscall_arch.h
new file mode 100644
index 0000000..fb3cc46
--- /dev/null
+++ b/arch/nt32/syscall_arch.h
@@ -0,0 +1,58 @@
+extern unsigned long ** __syscall_vtbl;
+
+typedef long __syscall0_fn(void);
+typedef long __syscall1_fn(long a1);
+typedef long __syscall2_fn(long a1, long a2);
+typedef long __syscall3_fn(long a1, long a2, long a3);
+typedef long __syscall4_fn(long a1, long a2, long a3, long a4);
+typedef long __syscall5_fn(long a1, long a2, long a3, long a4, long a5);
+typedef long __syscall6_fn(long a1, long a2, long a3, long a4, long a5, long a6);
+
+#define sysfn_from_fn(x) \
+	x * sysfn = (x *)__syscall_vtbl[n]
+
+static __inline long __syscall0(long n)
+{
+	sysfn_from_fn(__syscall0_fn);
+	return sysfn();
+}
+
+static __inline long __syscall1(long n, long a1)
+{
+	sysfn_from_fn(__syscall1_fn);
+	return sysfn(a1);
+}
+
+static __inline long __syscall2(long n, long a1, long a2)
+{
+	sysfn_from_fn(__syscall2_fn);
+	return sysfn(a1, a2);
+}
+
+static __inline long __syscall3(long n, long a1, long a2, long a3)
+{
+	sysfn_from_fn(__syscall3_fn);
+	return sysfn(a1, a2, a3);
+}
+
+static __inline long __syscall4(long n, long a1, long a2, long a3, long a4)
+{
+	sysfn_from_fn(__syscall4_fn);
+	return sysfn(a1, a2, a3, a4);
+}
+
+static __inline long __syscall5(long n, long a1, long a2, long a3, long a4, long a5)
+{
+	sysfn_from_fn(__syscall5_fn);
+	return sysfn(a1, a2, a3, a4, a5);
+}
+
+static __inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6)
+{
+	sysfn_from_fn(__syscall6_fn);
+	return sysfn(a1, a2, a3, a4, a5, a6);
+}
+
+
+#define __SYSCALL_LL_E(x) (x)
+#define __SYSCALL_LL_O(x) (x)
diff --git a/crt/nt32/Scrt1.c b/crt/nt32/Scrt1.c
new file mode 100644
index 0000000..ff5789f
--- /dev/null
+++ b/crt/nt32/Scrt1.c
@@ -0,0 +1,2 @@
+#define  LIBC_STATIC
+#include "crt1.c"
diff --git a/crt/nt32/crt1.c b/crt/nt32/crt1.c
new file mode 100644
index 0000000..6d22669
--- /dev/null
+++ b/crt/nt32/crt1.c
@@ -0,0 +1,33 @@
+#ifdef LIBC_STATIC
+#define __external_routine
+#else
+#define __external_routine __attribute__((dllimport))
+#endif
+
+#include "psxglue.h"
+
+/**
+ * options: posix session, fallback terminal emulator
+ * x86_64-nt64-midipix-gcc --target-help | grep -A2 posix
+**/
+
+static const int __disabled = 0;
+extern const int __crtopt_posix  __attribute((weak,alias("__disabled")));
+extern const int __crtopt_ttydbg __attribute((weak,alias("__disabled")));
+
+int main();
+
+__external_routine
+__psx_init_routine __psx_init;
+
+__external_routine
+void __libc_entry_routine(void *,void *,int);
+
+void _start(void)
+{
+	__libc_entry_routine(
+		main,
+		__psx_init,
+		__crtopt_posix | __crtopt_ttydbg);
+}
+
diff --git a/crt/nt32/crtdev.c b/crt/nt32/crtdev.c
new file mode 100644
index 0000000..8aa80e6
--- /dev/null
+++ b/crt/nt32/crtdev.c
@@ -0,0 +1,3 @@
+#include "psxglue.h"
+
+const int __crtopt_ttydbg = __PSXOPT_TTYDBG;
diff --git a/crt/nt32/crte.s b/crt/nt32/crte.s
new file mode 100644
index 0000000..56fa138
--- /dev/null
+++ b/crt/nt32/crte.s
@@ -0,0 +1,19 @@
+.text
+.globl __so_entry_point
+__so_entry_point:
+	cmp	$0x1,%edx
+	jne	_dso_main_routine
+	mov	%edx,%eax
+	ret
+
+___dso_main_routine:
+	ret
+
+	.weak	_dso_main_routine
+	.set	_dso_main_routine,___dso_main_routine
+
+.section .midipix
+	.long	_dso_main_routine
+	.long	__so_entry_point
+	.long	__init
+	.long	__fini
diff --git a/crt/nt32/crti.s b/crt/nt32/crti.s
new file mode 100644
index 0000000..7b1a642
--- /dev/null
+++ b/crt/nt32/crti.s
@@ -0,0 +1,41 @@
+.text
+.globl __pei386_runtime_relocator
+__pei386_runtime_relocator:
+	ret
+
+.globl __init
+__init:
+	call .init
+	ret
+
+.globl __fini
+__fini:
+	call .fini
+	ret
+
+.section .init
+	xor %eax,%eax
+	push %eax
+	push %ecx
+	push %edx
+	nop
+	nop
+
+.section .fini
+	xor %eax,%eax
+	push %eax
+	push %ecx
+	push %edx
+	nop
+	nop
+
+.section .midipix
+	.ascii "e35ed272"
+	.ascii "9e55"
+	.ascii "46c1"
+	.ascii "8251"
+	.ascii "022a59e6c480"
+	.long  0
+	.long  1
+	.long  0
+	.long  0
diff --git a/crt/nt32/crtn.s b/crt/nt32/crtn.s
new file mode 100644
index 0000000..2d0295e
--- /dev/null
+++ b/crt/nt32/crtn.s
@@ -0,0 +1,13 @@
+.section .init
+	pop %edx
+	pop %ecx
+	pop %ebx
+	or  %ebx,%eax
+	ret
+
+.section .fini
+	pop %edx
+	pop %ecx
+	pop %ebx
+	or  %ebx,%eax
+	ret
diff --git a/crt/nt32/crtposix.c b/crt/nt32/crtposix.c
new file mode 100644
index 0000000..b8e5113
--- /dev/null
+++ b/crt/nt32/crtposix.c
@@ -0,0 +1,3 @@
+#include "psxglue.h"
+
+const int __crtopt_posix = __PSXOPT_POSIX;
diff --git a/src/env/nt32/__environ.s b/src/env/nt32/__environ.s
new file mode 100644
index 0000000..62b9ee6
--- /dev/null
+++ b/src/env/nt32/__environ.s
@@ -0,0 +1,11 @@
+.globl	____environ
+.globl	___environ
+.globl	__environ
+.globl	_environ
+
+.data
+____environ:
+___environ:
+__environ:
+_environ:
+	.long	0
diff --git a/src/fcntl/nt32/posix_fadvise.c b/src/fcntl/nt32/posix_fadvise.c
new file mode 100644
index 0000000..c95d7f4
--- /dev/null
+++ b/src/fcntl/nt32/posix_fadvise.c
@@ -0,0 +1,14 @@
+#include "fcntl.h"
+#include "syscall_arch.h"
+
+int posix_fadvise (int fd, off_t base, off_t len, int advice)
+{
+	/**
+	 *  __syscall is needed here due to the odd semantics
+	 *  of posix_fadvise(), which for us means calling
+	 *  __sys_fadvise() directly.
+	**/
+
+	return 0; /* __sys_fadvise (fd, base, len, advice); */
+}
+
diff --git a/src/internal/nt32/libc.c b/src/internal/nt32/libc.c
new file mode 100644
index 0000000..43face8
--- /dev/null
+++ b/src/internal/nt32/libc.c
@@ -0,0 +1,7 @@
+#include "../libc.h"
+
+/* todo: teach the linker to export weak symbols */
+#undef  weak_alias
+#define weak_alias(old,new) extern __typeof(old) new __attribute__((alias(#old)))
+
+#include "../libc.c"
diff --git a/src/internal/nt32/syscall.s b/src/internal/nt32/syscall.s
new file mode 100644
index 0000000..3fcd5bb
--- /dev/null
+++ b/src/internal/nt32/syscall.s
@@ -0,0 +1,5 @@
+.text
+.global	___syscall
+
+___syscall:
+	jmp	___syscall_disp
diff --git a/src/ldso/nt32/dl_iterate_phdr.c b/src/ldso/nt32/dl_iterate_phdr.c
new file mode 100644
index 0000000..f98a509
--- /dev/null
+++ b/src/ldso/nt32/dl_iterate_phdr.c
@@ -0,0 +1,10 @@
+#include <stddef.h>
+#include <dlfcn.h>
+#include <link.h>
+
+typedef int __ldso_phdr_callback(struct dl_phdr_info * info, size_t size, void * data);
+
+int dl_iterate_phdr(__ldso_phdr_callback * callback, void * data)
+{
+	return -1;
+}
diff --git a/src/ldso/nt32/dynlink.c b/src/ldso/nt32/dynlink.c
new file mode 100644
index 0000000..c3cb23e
--- /dev/null
+++ b/src/ldso/nt32/dynlink.c
@@ -0,0 +1,62 @@
+#define _BSD_SOURCE
+
+#include <dlfcn.h>
+#include "psxglue.h"
+#include "pthread_impl.h"
+
+extern struct __ldso_vtbl * __ldso_vtbl;
+
+int __dladdr(const void * addr, Dl_info * info)
+{
+	return __ldso_vtbl->dladdr(addr,info);
+}
+
+int __dlinfo(void * dso, int req, void * res)
+{
+	return __ldso_vtbl->dlinfo(dso,req,res);
+}
+
+void *__dlsym(void * restrict p, const char * restrict s, void * restrict ra)
+{
+	return __ldso_vtbl->dlsym(p,s,ra);
+}
+
+void * dlopen(const char * file, int mode)
+{
+	return __ldso_vtbl->dlopen(file,mode);
+}
+
+int dlclose(void *p)
+{
+        return __ldso_vtbl->dlclose(p);
+}
+
+char * dlerror(void)
+{
+	return __ldso_vtbl->dlerror();
+}
+
+void __reset_tls(void)
+{
+	__ldso_vtbl->reset_tls();
+}
+
+void *__copy_tls(unsigned char * mem)
+{
+	/**
+	 * this is always the simple case, since:
+	 * emutls is based on PE named sections; and
+	 * tls allocation and initialization are handled by clone(2)
+	**/
+
+        pthread_t td;
+        void **	  dtv;
+
+	dtv = (void **)mem;
+	dtv[0] = 0;
+
+	td = (void *)(dtv + 1);
+	td->dtv = dtv;
+
+	return td;
+}
diff --git a/src/ldso/nt32/start.s b/src/ldso/nt32/start.s
new file mode 100644
index 0000000..32dc52f
--- /dev/null
+++ b/src/ldso/nt32/start.s
@@ -0,0 +1,2 @@
+# standard dynamic loader is not required
+# optional dynamic loader [to be] provided by libldso/libpsxscl
diff --git a/src/ldso/nt32/tlsdesc.c b/src/ldso/nt32/tlsdesc.c
new file mode 100644
index 0000000..7015e30
--- /dev/null
+++ b/src/ldso/nt32/tlsdesc.c
@@ -0,0 +1,8 @@
+#include <stddef.h>
+
+ptrdiff_t __tlsdesc_static(void)
+{
+	return 0;
+}
+
+ptrdiff_t  __tlsdesc_dynamic(void) __attribute__((alias("__tlsdesc_static")));
diff --git a/src/setjmp/nt32/longjmp.s b/src/setjmp/nt32/longjmp.s
new file mode 100644
index 0000000..095a47f
--- /dev/null
+++ b/src/setjmp/nt32/longjmp.s
@@ -0,0 +1,9 @@
+.text
+.globl	___longjmp
+.globl	__longjmp
+.globl	_longjmp
+
+___longjmp:
+__longjmp:
+_longjmp:
+	test %edx, %edx		# is val zero?
diff --git a/src/setjmp/nt32/setjmp.s b/src/setjmp/nt32/setjmp.s
new file mode 100644
index 0000000..1865f0c
--- /dev/null
+++ b/src/setjmp/nt32/setjmp.s
@@ -0,0 +1,14 @@
+.text
+.globl	___setjmp
+.globl	__setjmp
+.globl	_setjmp
+
+___setjmp:
+__setjmp:
+_setjmp:
+	pop  (%ecx)		# return address
+	mov  %esp, 0x04(%ecx)	# caller's stack pointer
+	push (%ecx)		# restore own stack pointer
+
+	xor %eax,  %eax
+	ret
diff --git a/src/stdio/nt32/fflush.c b/src/stdio/nt32/fflush.c
new file mode 100644
index 0000000..4c88f20
--- /dev/null
+++ b/src/stdio/nt32/fflush.c
@@ -0,0 +1,6 @@
+#include "../fflush.c"
+
+int __fflush_unlocked_impl(FILE *f)
+{
+	return __fflush_unlocked(f);
+}
diff --git a/src/thread/nt32/__set_thread_area.c b/src/thread/nt32/__set_thread_area.c
new file mode 100644
index 0000000..c50f6c6
--- /dev/null
+++ b/src/thread/nt32/__set_thread_area.c
@@ -0,0 +1,13 @@
+#include <errno.h>
+#include "pthread_impl.h"
+
+int __set_thread_area(void * p)
+{
+	struct pthread ** ptlca;
+
+	ptlca = __psx_tlca();
+	if (!ptlca) return -ESRCH;
+
+	*ptlca = p;
+	return 0;
+}
diff --git a/src/thread/nt32/__tls_get_addr.c b/src/thread/nt32/__tls_get_addr.c
new file mode 100644
index 0000000..ad8d845
--- /dev/null
+++ b/src/thread/nt32/__tls_get_addr.c
@@ -0,0 +1,2 @@
+/* using a custom, register-based __emutls_get_address */
+typedef int dummy;
diff --git a/src/thread/nt32/clone.c b/src/thread/nt32/clone.c
new file mode 100644
index 0000000..fb53501
--- /dev/null
+++ b/src/thread/nt32/clone.c
@@ -0,0 +1,54 @@
+#include <syscall.h>
+
+struct pt_regs {
+	unsigned long	ebp;
+	unsigned long	ebx;
+	unsigned long	eax;
+	unsigned long	ecx;
+	unsigned long	edx;
+	unsigned long	esi;
+	unsigned long	edi;
+	unsigned long	orig_eax;
+	unsigned long	eip;
+	unsigned long	cs;
+	unsigned long	eflags;
+	unsigned long	esp;
+	unsigned long	ss;
+};
+
+typedef long __sys_clone(
+	unsigned long	flags,
+	void *		child_stack,
+	void *		ptid,
+	void *		ctid,
+	struct pt_regs *regs);
+
+typedef int __entry_point(void *);
+
+extern unsigned long ** __syscall_vtbl;
+
+int __clone(
+	__entry_point *	fn,
+	void *		child_stack,
+	int		flags,
+	void *		arg,
+	int *		ptid,
+	void *		pthread_self_addr,
+	int *		ctid)
+{
+	struct pt_regs	regs;
+	__sys_clone *	pfn_clone;
+
+	regs.eip = (unsigned long)fn;
+	regs.ecx = (unsigned long)arg;
+	regs.edx = (unsigned long)pthread_self_addr;
+
+	pfn_clone = (__sys_clone *)(__syscall_vtbl[SYS_clone]);
+
+	return (int)pfn_clone(
+		flags,
+		child_stack,
+		ptid,
+		ctid,
+		&regs);
+}
diff --git a/src/thread/nt32/pthread_detach.c b/src/thread/nt32/pthread_detach.c
new file mode 100644
index 0000000..85db4cb
--- /dev/null
+++ b/src/thread/nt32/pthread_detach.c
@@ -0,0 +1,6 @@
+#include "../pthread_detach.c"
+
+int __pthread_detach_impl(pthread_t t)
+{
+	return thrd_detach(t);
+}
diff --git a/src/thread/nt32/pthread_equal.c b/src/thread/nt32/pthread_equal.c
new file mode 100644
index 0000000..a8fcd79
--- /dev/null
+++ b/src/thread/nt32/pthread_equal.c
@@ -0,0 +1,6 @@
+#include "../pthread_equal.c"
+
+int __pthread_equal_impl(pthread_t a, pthread_t b)
+{
+	return thrd_equal(a,b);
+}
diff --git a/src/thread/nt32/pthread_self.c b/src/thread/nt32/pthread_self.c
new file mode 100644
index 0000000..23fbc53
--- /dev/null
+++ b/src/thread/nt32/pthread_self.c
@@ -0,0 +1,10 @@
+#include "pthread_impl.h"
+#include <threads.h>
+#include "libc.h"
+
+pthread_t pthread_self()
+{
+	return __pthread_self();
+}
+
+weak_alias(pthread_self, thrd_current);
diff --git a/src/thread/nt32/syscall_cp.s b/src/thread/nt32/syscall_cp.s
new file mode 100644
index 0000000..c52731f
--- /dev/null
+++ b/src/thread/nt32/syscall_cp.s
@@ -0,0 +1,15 @@
+.text
+.globl	___syscall_cp_asm
+.globl	___cp_begin
+.globl	___cp_end
+
+___syscall_cp_asm:
+___cp_begin:
+	mov 	(%ecx),	%ecx	/* check content of ptr */
+	test	%ecx,	%ecx
+	jnz	___cancel	/* thread is pending cancellation */
+
+	jmp	___syscall
+
+___cp_end:
+	ret