summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--arch/nt64/atomic.h7
-rw-r--r--arch/nt64/psxglue.h63
-rw-r--r--arch/nt64/pthread_arch.h74
-rw-r--r--arch/nt64/reloc.h6
-rw-r--r--arch/nt64/src/crt_glue.c87
-rw-r--r--arch/nt64/src/crt_pe.c7
-rw-r--r--arch/nt64/src/crt_tls.c27
-rw-r--r--arch/nt64/src/libc_entry_point.c10
-rw-r--r--arch/nt64/src/syscall_disp.c22
-rw-r--r--arch/nt64/src/vtbl.c12
-rw-r--r--arch/nt64/syscall_arch.h63
-rw-r--r--crt/nt64/Scrt1.c2
-rw-r--r--crt/nt64/crt1.c33
-rw-r--r--crt/nt64/crtdev.c3
-rw-r--r--crt/nt64/crte.s19
-rw-r--r--crt/nt64/crti.s41
-rw-r--r--crt/nt64/crtn.s13
-rw-r--r--crt/nt64/crtposix.c3
-rw-r--r--musl.lzy389
-rw-r--r--src/env/nt64/__environ.s11
-rw-r--r--src/fcntl/nt64/posix_fadvise.c14
-rw-r--r--src/internal/nt64/libc.c7
-rw-r--r--src/internal/nt64/syscall.s5
-rw-r--r--src/ldso/nt64/dl_iterate_phdr.c10
-rw-r--r--src/ldso/nt64/dynlink.c58
-rw-r--r--src/ldso/nt64/start.s2
-rw-r--r--src/ldso/nt64/tlsdesc.c8
-rw-r--r--src/setjmp/nt64/longjmp.s28
-rw-r--r--src/setjmp/nt64/setjmp.s23
-rw-r--r--src/thread/nt64/__set_thread_area.c13
-rw-r--r--src/thread/nt64/__tls_get_addr.c2
-rw-r--r--src/thread/nt64/clone.c62
-rw-r--r--src/thread/nt64/pthread_detach.c6
-rw-r--r--src/thread/nt64/pthread_equal.c6
-rw-r--r--src/thread/nt64/pthread_self.c10
-rw-r--r--src/thread/nt64/syscall_cp.s29
36 files changed, 1175 insertions, 0 deletions
diff --git a/arch/nt64/atomic.h b/arch/nt64/atomic.h
new file mode 100644
index 0000000..a2b141a
--- /dev/null
+++ b/arch/nt64/atomic.h
@@ -0,0 +1,7 @@
+#ifndef _INTERNAL_ATOMIC_NT64_H
+#define _INTERNAL_ATOMIC_NT64_H
+
+#include "../x86_64/atomic.h"
+
+#endif
+
diff --git a/arch/nt64/psxglue.h b/arch/nt64/psxglue.h
new file mode 100644
index 0000000..73ad2b0
--- /dev/null
+++ b/arch/nt64/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/nt64/pthread_arch.h b/arch/nt64/pthread_arch.h
new file mode 100644
index 0000000..98babcd
--- /dev/null
+++ b/arch/nt64/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 %%gs:0x30, %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+
+static inline void __pthread_convert(void)
+{
+ /* (third-party thread support) */
+ __asm__ __volatile__ (
+ "push %rax\n\t"
+ "movq __psx_vtbl,%rax\n\t"
+ "call *(%rax)\n\t"
+ "pop %rax\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 + 0x1480);
+ ptlca = (struct pthread **)(slots[sys_idx]);
+ } else {
+ xslots = (void ***)((uintptr_t)tib + 0x1780);
+ 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/nt64/reloc.h b/arch/nt64/reloc.h
new file mode 100644
index 0000000..20abf44
--- /dev/null
+++ b/arch/nt64/reloc.h
@@ -0,0 +1,6 @@
+#define LDSO_ARCH "PE32+"
+
+static int remap_rel(int type)
+{
+ return 0;
+}
diff --git a/arch/nt64/src/crt_glue.c b/arch/nt64/src/crt_glue.c
new file mode 100644
index 0000000..e8a07de
--- /dev/null
+++ b/arch/nt64/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_routine,
+ 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_routine(&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/nt64/src/crt_pe.c b/arch/nt64/src/crt_pe.c
new file mode 100644
index 0000000..0dc75a4
--- /dev/null
+++ b/arch/nt64/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/nt64/src/crt_tls.c b/arch/nt64/src/crt_tls.c
new file mode 100644
index 0000000..15183d3
--- /dev/null
+++ b/arch/nt64/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/nt64/src/libc_entry_point.c b/arch/nt64/src/libc_entry_point.c
new file mode 100644
index 0000000..0929cc4
--- /dev/null
+++ b/arch/nt64/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/nt64/src/syscall_disp.c b/arch/nt64/src/syscall_disp.c
new file mode 100644
index 0000000..cb9655d
--- /dev/null
+++ b/arch/nt64/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,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/nt64/src/vtbl.c b/arch/nt64/src/vtbl.c
new file mode 100644
index 0000000..028f153
--- /dev/null
+++ b/arch/nt64/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/nt64/syscall_arch.h b/arch/nt64/syscall_arch.h
new file mode 100644
index 0000000..9c8fea4
--- /dev/null
+++ b/arch/nt64/syscall_arch.h
@@ -0,0 +1,63 @@
+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)
+
+
+#define VDSO_USEFUL
+#define VDSO_CGT_SYM "__clock_gettime"
+#define VDSO_CGT_VER "LINUX_2.6"
diff --git a/crt/nt64/Scrt1.c b/crt/nt64/Scrt1.c
new file mode 100644
index 0000000..ff5789f
--- /dev/null
+++ b/crt/nt64/Scrt1.c
@@ -0,0 +1,2 @@
+#define LIBC_STATIC
+#include "crt1.c"
diff --git a/crt/nt64/crt1.c b/crt/nt64/crt1.c
new file mode 100644
index 0000000..6d22669
--- /dev/null
+++ b/crt/nt64/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/nt64/crtdev.c b/crt/nt64/crtdev.c
new file mode 100644
index 0000000..8aa80e6
--- /dev/null
+++ b/crt/nt64/crtdev.c
@@ -0,0 +1,3 @@
+#include "psxglue.h"
+
+const int __crtopt_ttydbg = __PSXOPT_TTYDBG;
diff --git a/crt/nt64/crte.s b/crt/nt64/crte.s
new file mode 100644
index 0000000..9753213
--- /dev/null
+++ b/crt/nt64/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
+ .quad dso_main_routine
+ .quad _so_entry_point
+ .quad _init
+ .quad _fini
diff --git a/crt/nt64/crti.s b/crt/nt64/crti.s
new file mode 100644
index 0000000..14fdd90
--- /dev/null
+++ b/crt/nt64/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 %rax,%rax
+ push %rax
+ push %rcx
+ push %rdx
+ nop
+ nop
+
+.section .fini
+ xor %rax,%rax
+ push %rax
+ push %rcx
+ push %rdx
+ 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/nt64/crtn.s b/crt/nt64/crtn.s
new file mode 100644
index 0000000..b2c7790
--- /dev/null
+++ b/crt/nt64/crtn.s
@@ -0,0 +1,13 @@
+.section .init
+ pop %rdx
+ pop %rcx
+ pop %r10
+ or %r10,%rax
+ ret
+
+.section .fini
+ pop %rdx
+ pop %rcx
+ pop %r10
+ or %r10,%rax
+ ret
diff --git a/crt/nt64/crtposix.c b/crt/nt64/crtposix.c
new file mode 100644
index 0000000..b8e5113
--- /dev/null
+++ b/crt/nt64/crtposix.c
@@ -0,0 +1,3 @@
+#include "psxglue.h"
+
+const int __crtopt_posix = __PSXOPT_POSIX;
diff --git a/musl.lzy b/musl.lzy
new file mode 100644
index 0000000..b3f0f4e
--- /dev/null
+++ b/musl.lzy
@@ -0,0 +1,389 @@
+# lazy mark: project recipe
+lz_project_rules()
+{
+ lz_rules="all install install_no_complex \
+ libc libc_shared libc_static \
+ libc_no_complex libc_shared_no_complex libc_static_no_complex"
+}
+
+
+lz_project_definitions()
+{
+ lz_cflags_common="-std=c99 -pipe -ffreestanding -nostdinc -D_XOPEN_SOURCE=700 -fomit-frame-pointer"
+
+ lz_cflags_include_common="-I$lz_project_dir/src/internal \
+ -I$lz_project_dir/arch/$lz_arch \
+ -I$lz_project_dir/include \
+ -I$lz_build_dir/arch/$lz_arch \
+ -I$lz_build_dir/include"
+
+ musl_empty_lib_names="m rt pthread crypt util xnet resolv dl"
+ musl_cflags_crt="-fPIC"
+ musl_cflags_shared="-fPIC -DSHARED"
+
+ if [ "$lz_pecoff_winnt"x = yesx ]; then
+ pe_excluded_symbols="__libc_entry_point"
+ pe_excluded_symbols="$pe_excluded_symbols,__syscall_vtbl"
+ pe_excluded_symbols="$pe_excluded_symbols,__ldso_vtbl"
+ pe_excluded_symbols="$pe_excluded_symbols,__psx_vtbl"
+ pe_excluded_symbols="$pe_excluded_symbols,__teb_sys_idx"
+ pe_excluded_symbols="$pe_excluded_symbols,__teb_libc_idx"
+ pe_excluded_symbols="$pe_excluded_symbols,__vm_lock_impl"
+ pe_excluded_symbols="$pe_excluded_symbols,__vm_unlock_impl"
+
+ musl_libc_so_ldflags="-shared -e __libc_entry_point -Bsymbolic-functions \
+ --subsystem windows \
+ --output-def $lz_build_dir/lib/libc.so.def \
+ --out-implib $lz_build_dir/lib/libc.lib.a \
+ --exclude-symbols=$pe_excluded_symbols"
+ else
+ musl_libc_so_ldflags="-shared -e _start -Bsymbolic-functions"
+ fi
+
+ musl_libc_src_dirs="src arch/$lz_arch/src arch/$lz_arch/weak"
+ musl_libc_mem_files="src/string/memcpy.c src/string/memmove.c src/string/memcmp.c src/string/memset.c"
+
+
+ lz_flag_tests_begin
+
+ for musl_test_flag in "-frounding-math" "-fexcess-precision=standard"; do
+ lz_compiler_supports_flag $lz_c_compiler "$musl_test_flag" \
+ && lz_cflags_common="$lz_cflags_common $musl_test_flag"
+ done
+
+ for musl_test_flag in "-fno-tree-loop-distribute-patterns"; do
+ lz_compiler_supports_flag $lz_c_compiler "$musl_test_flag" \
+ && musl_cflags_memops="$musl_cflags_memops $musl_test_flag"
+ done
+
+ for musl_test_flag in "--hash-style=both"; do
+ lz_linker_supports_flag $lz_c_compiler $lz_ld "$musl_test_flag" \
+ && musl_libc_so_ldflags="$musl_libc_so_ldflags $musl_test_flag"
+ done
+
+ lz_flag_tests_end
+
+
+ if [ "$lz_debug"x = yesx ]; then
+ lz_cflags_debug="$lz_toolchain_cflags_debug"
+ else
+ lz_cflags_common="$lz_cflags_common -Os"
+ fi
+
+ # names of binary files and/or utilities
+ musl_libc_a_name="$lz_build_dir/lib/libc$lz_stlib_ext"
+ musl_libc_so_name="$lz_build_dir/lib/libc$lz_dylib_ext"
+
+ # temporary files to store meta information
+ musl_libc_so_obj_list=libc.so.objs
+ musl_libc_so_src_list=libc.so.src.lst
+
+ musl_libc_a_obj_list=libc.a.objs
+ musl_libc_a_src_list=libc.a.src.lst
+
+ musl_crt_obj_list=crt.objs
+ musl_crt_src_list=crt.src.lst
+
+ musl_install_sh=$lz_project_dir/tools/install.sh
+ musl_ldso="$lz_syslibdir/ld-musl-$lz_arch$lz_subarch.so.1"
+}
+
+
+musl_headers()
+{
+ if [ -f $lz_build_dir/headers.tag ]; then
+ lz_ok && return
+ fi
+
+ mkdir -p $lz_build_dir/include
+ cp -r -t $lz_build_dir/include $lz_project_dir/arch/$lz_arch/bits
+
+ touch $lz_build_dir/headers.tag
+}
+
+
+musl_alltypes()
+{
+ if [ -f $lz_build_dir/alltypes.tag ]; then
+ lz_ok && return
+ fi
+
+ sed -f $lz_project_dir/tools/mkalltypes.sed \
+ $lz_build_dir/include/bits/alltypes.h.in \
+ $lz_project_dir/include/alltypes.h.in > \
+ $lz_build_dir/include/bits/alltypes.h
+
+ touch $lz_build_dir/alltypes.tag
+}
+
+
+musl_version()
+{
+ if [ -f $lz_build_dir/version.tag ]; then
+ lz_ok && return
+ fi
+
+ lz_pushd $lz_project_dir
+ lzp_version=`sh tools/version.sh`
+ lz_popd
+
+ printf '#define VERSION "%s"\n' $lzp_version \
+ > $lz_build_dir/include/version.h
+
+ touch $lz_build_dir/version.tag
+}
+
+
+musl_empty_libs()
+{
+ if [ -f $lz_build_dir/empty_libs.tag ]; then
+ lz_ok && return
+ fi
+
+ for lzp_lib_name in $musl_empty_lib_names; do
+ lzp_lib_file_name=$lz_build_dir/lib/lib$lzp_lib_name.a
+ rm -f $lzp_lib_file_name
+ $lz_ar rc $lzp_lib_file_name
+ done
+
+ touch $lz_build_dir/empty_libs.tag
+}
+
+musl_crt()
+{
+ musl_headers
+ musl_alltypes
+
+ lz_cflags_extra="$musl_cflags_crt"
+ lz_src_dirs="crt"
+
+ lz_compile "$musl_crt_obj_list" "$musl_crt_src_list" "$lz_stobj_ext"
+}
+
+
+musl_libc_common()
+{
+ musl_headers
+ musl_alltypes
+ musl_version
+}
+
+
+musl_libc_shared()
+{
+ musl_libc_common
+ musl_crt
+
+ # memory functions
+ lz_cflags_extra="$musl_cflags_shared"
+ lz_cflags_special="$musl_cflags_memops"
+ lz_src_files="$musl_libc_mem_files"
+ lz_src_dirs=$lz_ignore_src_dirs
+
+ lz_compile "$musl_libc_so_obj_list" "$musl_libc_so_src_list" "$lz_dyobj_ext"
+
+ lz_src_files=
+ lz_cflags_special=
+
+ # regular source files
+ lz_cumulative_obj_list=yes
+ lz_src_dirs=$musl_libc_src_dirs
+ lz_exclude_src_files="$musl_libc_mem_files"
+ lz_compiler_rt_libs="$lz_compiler_rt_libs $lz_link_libgcc"
+
+ if [ "$lz_pecoff_winnt"x = yesx ]; then
+ musl_crti_objs="musl_crti_objs.lst"
+ musl_crtn_objs="musl_crtn_objs.lst"
+ echo 'crt/crti.o' > $musl_crti_objs
+ echo 'crt/crtn.o' > $musl_crtn_objs
+ else
+ musl_crti_objs=
+ musl_crtn_objs=
+ fi
+
+ rm -f "$musl_libc_so_name"
+
+ lz_compile "$musl_libc_so_obj_list" "$musl_libc_so_src_list" "$lz_dyobj_ext"
+ lz_link "$musl_crti_objs $musl_libc_so_obj_list $musl_crtn_objs" \
+ "$musl_libc_so_src_list" \
+ "$musl_libc_so_name" \
+ "$musl_libc_so_ldflags" \
+ "$lz_compiler_rt_libs" \
+ "$lz_arch_dynamic_syscall_libs"
+}
+
+
+musl_libc_static()
+{
+ musl_libc_common
+
+ # memory functions
+ lz_cflags_special="$musl_cflags_memops"
+ lz_src_files="$musl_libc_mem_files"
+ lz_src_dirs=$lz_ignore_src_dirs
+
+ lz_compile "$musl_libc_a_obj_list" "$musl_libc_a_src_list" "$lz_stobj_ext"
+ lz_src_files=
+ lz_cflags_special=
+
+ # regular source files
+ lz_cumulative_obj_list=yes
+ lz_src_dirs=$musl_libc_src_dirs
+ lz_exclude_src_files="$musl_libc_mem_files"
+
+ rm -f "$musl_libc_a_name"
+
+ lz_compile "$musl_libc_a_obj_list" "$musl_libc_a_src_list" "$lz_stobj_ext"
+ lz_archive "$musl_libc_a_obj_list" "$musl_libc_a_src_list" "$musl_libc_a_name"
+
+ if [ "$lz_pecoff_winnt"x = yesx ]; then
+ if [ "$lz_arch_dynamic_syscall_libs"x != x ]; then
+ $lz_ar rc "$musl_libc_a_name" "$lz_arch_static_syscall_libs"
+ fi
+ fi
+}
+
+
+musl_libc_shared_no_complex()
+{
+ lz_link_libgcc=
+ lz_exclude_src_dirs="src/complex"
+ musl_libc_shared
+}
+
+
+musl_libc_static_no_complex()
+{
+ lz_exclude_src_dirs="src/complex"
+ musl_libc_static
+}
+
+
+musl_libc()
+{
+ lz_link_libgcc="--as-needed `$lz_c_compiler -print-file-name=libgcc.a`"
+ lz_step musl_crt
+ lz_step musl_libc_shared
+ lz_step musl_libc_static
+ lz_step musl_empty_libs
+}
+
+
+musl_libc_no_complex()
+{
+ lz_step musl_crt
+ lz_step musl_libc_shared_no_complex
+ lz_step musl_libc_static_no_complex
+ lz_step musl_empty_libs
+}
+
+
+musl_all()
+{
+ lz_step musl_libc
+}
+
+
+musl_install_crt()
+{
+ lz_pushd $lz_build_dir/crt
+
+ musl_crt_files=`cat $lz_build_dir/crt.objs`
+
+ for lzp_crt_file in $musl_crt_files; do
+ lzp_crt_obj_file=`basename $lzp_crt_file`
+ $musl_install_sh -D $lzp_crt_obj_file $lz_libdir/$lzp_crt_obj_file
+ done
+
+ lz_popd
+}
+
+
+musl_install_libs()
+{
+ lz_pushd $lz_build_dir/lib
+
+ for lzp_lib_file in "c" $musl_empty_lib_names; do
+ $musl_install_sh -D -m 644 lib$lzp_lib_file$lz_stlib_ext $lz_libdir/lib$lzp_lib_file$lz_stlib_ext
+ done
+
+ $musl_install_sh -D -m 755 libc$lz_dylib_ext $lz_libdir/libc$lz_dylib_ext
+
+ if [ "$lz_pecoff_winnt"x = yesx ]; then
+ # also install the import library
+ $musl_install_sh -D -m 644 libc$lz_implib_ext $lz_libdir/libc$lz_implib_ext
+ fi
+
+ lz_popd
+}
+
+
+musl_install_ldso()
+{
+ $musl_install_sh -D -l $lz_libdir/libc$lz_dylib_ext $musl_ldso
+ $musl_install_sh -D -l $lz_libdir/libc$lz_dylib_ext $lz_bindir/ldd
+}
+
+
+musl_install_headers()
+{
+ lz_pushd $lz_project_dir/include
+
+ musl_include_files=`find . -type f`
+
+ for lzp_include_file in $musl_include_files; do
+ $musl_install_sh -D -m 644 $lzp_include_file $lz_includedir/$lzp_include_file
+ done
+
+ lz_popd
+}
+
+
+musl_install_arch_headers()
+{
+ lz_pushd $lz_build_dir/include
+
+ musl_include_files=`find ./bits -type f ! -name *.h.in`
+
+ for lzp_include_file in $musl_include_files; do
+ $musl_install_sh -D -m 644 $lzp_include_file $lz_includedir/$lzp_include_file
+ done
+
+ lz_popd
+}
+
+
+musl_install_specs()
+{
+ sh $lz_project_dir/tools/musl-gcc.specs.sh \
+ $(readlink -f "$lz_includedir") \
+ $(readlink -f "$lz_libdir") \
+ $(readlink -f "$musl_ldso") \
+ > $lz_libdir/musl-gcc.specs
+}
+
+
+musl_install_common()
+{
+ lz_step musl_install_crt
+ lz_step musl_install_libs
+ lz_step musl_install_ldso
+ lz_step musl_install_headers
+ lz_step musl_install_arch_headers
+ lz_step musl_install_specs
+}
+
+
+musl_install()
+{
+ lz_step musl_all
+ lz_step musl_install_common
+}
+
+
+musl_install_no_complex()
+{
+ lz_step musl_libc_no_complex
+ lz_step musl_install_common
+}
+
diff --git a/src/env/nt64/__environ.s b/src/env/nt64/__environ.s
new file mode 100644
index 0000000..28ac875
--- /dev/null
+++ b/src/env/nt64/__environ.s
@@ -0,0 +1,11 @@
+.globl ___environ
+.globl __environ
+.globl _environ
+.globl environ
+
+.data
+___environ:
+__environ:
+_environ:
+environ:
+ .quad 0
diff --git a/src/fcntl/nt64/posix_fadvise.c b/src/fcntl/nt64/posix_fadvise.c
new file mode 100644
index 0000000..c95d7f4
--- /dev/null
+++ b/src/fcntl/nt64/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/nt64/libc.c b/src/internal/nt64/libc.c
new file mode 100644
index 0000000..43face8
--- /dev/null
+++ b/src/internal/nt64/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/nt64/syscall.s b/src/internal/nt64/syscall.s
new file mode 100644
index 0000000..ce3827b
--- /dev/null
+++ b/src/internal/nt64/syscall.s
@@ -0,0 +1,5 @@
+.text
+.global __syscall
+
+__syscall:
+ jmp __syscall_disp
diff --git a/src/ldso/nt64/dl_iterate_phdr.c b/src/ldso/nt64/dl_iterate_phdr.c
new file mode 100644
index 0000000..f98a509
--- /dev/null
+++ b/src/ldso/nt64/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/nt64/dynlink.c b/src/ldso/nt64/dynlink.c
new file mode 100644
index 0000000..e5329e6
--- /dev/null
+++ b/src/ldso/nt64/dynlink.c
@@ -0,0 +1,58 @@
+#define _BSD_SOURCE
+
+#include <dlfcn.h>
+#include "pthread_impl.h"
+
+int __dladdr(const void * addr, Dl_info * info)
+{
+ return 0;
+}
+
+int __dlinfo(void * dso, int req, void * res)
+{
+ return 0;
+}
+
+void *__dlsym(void * restrict p, const char * restrict s, void * restrict ra)
+{
+ return 0;
+}
+
+void * dlopen(const char * file, int mode)
+{
+ return 0;
+}
+
+int dlclose(void *p)
+{
+ return 0;
+}
+
+char * dlerror(void)
+{
+ return 0;
+}
+
+void __reset_tls(void)
+{
+}
+
+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/nt64/start.s b/src/ldso/nt64/start.s
new file mode 100644
index 0000000..32dc52f
--- /dev/null
+++ b/src/ldso/nt64/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/nt64/tlsdesc.c b/src/ldso/nt64/tlsdesc.c
new file mode 100644
index 0000000..7015e30
--- /dev/null
+++ b/src/ldso/nt64/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/nt64/longjmp.s b/src/setjmp/nt64/longjmp.s
new file mode 100644
index 0000000..0fcf52e
--- /dev/null
+++ b/src/setjmp/nt64/longjmp.s
@@ -0,0 +1,28 @@
+.text
+.globl __longjmp
+.globl _longjmp
+.globl longjmp
+
+__longjmp:
+_longjmp:
+longjmp:
+ test %edx, %edx # is val zero?
+ jne 1f # no: return val
+ xor $1, %edx # yes: return one
+
+1:
+ mov %edx, %eax # return value
+
+2:
+ mov 0x10(%rcx), %rbx # restore regs
+ mov 0x18(%rcx), %rbp
+ mov 0x20(%rcx), %rdi
+ mov 0x28(%rcx), %rsi
+ mov 0x30(%rcx), %r12
+ mov 0x38(%rcx), %r13
+ mov 0x40(%rcx), %r14
+ mov 0x48(%rcx), %r15
+
+ mov 0x08(%rcx), %rsp # saved stack pointer
+ mov (%rcx), %rdx # return address
+ jmp *%rdx # return
diff --git a/src/setjmp/nt64/setjmp.s b/src/setjmp/nt64/setjmp.s
new file mode 100644
index 0000000..3e8a1ea
--- /dev/null
+++ b/src/setjmp/nt64/setjmp.s
@@ -0,0 +1,23 @@
+.text
+.globl __setjmp
+.globl _setjmp
+.globl setjmp
+
+__setjmp:
+_setjmp:
+setjmp:
+ pop (%rcx) # return address
+ mov %rsp, 0x08(%rcx) # caller's stack pointer
+ push (%rcx) # restore own stack pointer
+
+ mov %rbx, 0x10(%rcx)
+ mov %rbp, 0x18(%rcx)
+ mov %rdi, 0x20(%rcx)
+ mov %rsi, 0x28(%rcx)
+ mov %r12, 0x30(%rcx)
+ mov %r13, 0x38(%rcx)
+ mov %r14, 0x40(%rcx)
+ mov %r15, 0x48(%rcx)
+
+ xor %eax, %eax
+ ret
diff --git a/src/thread/nt64/__set_thread_area.c b/src/thread/nt64/__set_thread_area.c
new file mode 100644
index 0000000..c50f6c6
--- /dev/null
+++ b/src/thread/nt64/__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/nt64/__tls_get_addr.c b/src/thread/nt64/__tls_get_addr.c
new file mode 100644
index 0000000..ad8d845
--- /dev/null
+++ b/src/thread/nt64/__tls_get_addr.c
@@ -0,0 +1,2 @@
+/* using a custom, register-based __emutls_get_address */
+typedef int dummy;
diff --git a/src/thread/nt64/clone.c b/src/thread/nt64/clone.c
new file mode 100644
index 0000000..d460855
--- /dev/null
+++ b/src/thread/nt64/clone.c
@@ -0,0 +1,62 @@
+#include <syscall.h>
+
+struct pt_regs {
+ unsigned long r15;
+ unsigned long r14;
+ unsigned long r13;
+ unsigned long r12;
+ unsigned long rbp;
+ unsigned long rbx;
+ unsigned long r11;
+ unsigned long r10;
+ unsigned long r9;
+ unsigned long r8;
+ unsigned long rax;
+ unsigned long rcx;
+ unsigned long rdx;
+ unsigned long rsi;
+ unsigned long rdi;
+ unsigned long orig_rax;
+ unsigned long rip;
+ unsigned long cs;
+ unsigned long eflags;
+ unsigned long rsp;
+ 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.rip = (unsigned long)fn;
+ regs.rcx = (unsigned long)arg;
+ regs.rdx = (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/nt64/pthread_detach.c b/src/thread/nt64/pthread_detach.c
new file mode 100644
index 0000000..85db4cb
--- /dev/null
+++ b/src/thread/nt64/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/nt64/pthread_equal.c b/src/thread/nt64/pthread_equal.c
new file mode 100644
index 0000000..a8fcd79
--- /dev/null
+++ b/src/thread/nt64/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/nt64/pthread_self.c b/src/thread/nt64/pthread_self.c
new file mode 100644
index 0000000..23fbc53
--- /dev/null
+++ b/src/thread/nt64/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/nt64/syscall_cp.s b/src/thread/nt64/syscall_cp.s
new file mode 100644
index 0000000..b8b7039
--- /dev/null
+++ b/src/thread/nt64/syscall_cp.s
@@ -0,0 +1,29 @@
+.text
+.globl __syscall_cp_asm
+.globl __cp_begin
+.globl __cp_end
+
+__syscall_cp_asm:
+__cp_begin:
+ movq (%rcx), %rcx /* check content of ptr */
+ test %ecx, %ecx
+ jnz __cancel /* thread is pending cancellation */
+
+ movq %rdx, %rcx/* move water */
+ movq %r8, %rdx/* from one glass */
+ movq %r9, %r8 /* to another */
+ movq 0x28(%rsp), %r9
+
+ movq 0x30(%rsp),%rax
+ movq %rax, 0x28(%rsp)
+
+ movq 0x38(%rsp),%r10
+ movq %r10, 0x30(%rsp)
+
+ movq 0x40(%rsp),%r10
+ movq %r10, 0x38(%rsp)
+
+ jmp __syscall
+
+__cp_end:
+ ret