[uclibc-ng-devel] csky: port to uclibc-ng

Message ID 1508072374-22032-1-git-send-email-ren_guo@c-sky.com
State New
Headers show
Series
  • [uclibc-ng-devel] csky: port to uclibc-ng
Related show

Commit Message

Guo Ren Oct. 15, 2017, 12:59 p.m.
Follow the steps to build c-sky uclibc linux system:
1. git clone https://github.com/c-sky/buildroot.git
2. cd buildroot
3. make qemu_csky_ck810_uclibc_defconfig
4. make

Follow the buildroot/board/qemu/csky/readme.txt to run.

This buildroot toolchain is pre-build, But you can rebuild
the c-sky uclibc-ng alone and install it to the buildroot
sysroot manually.

We'll try our best to improve the uclibc-ng continuously.

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 MAINTAINERS                                        |   3 +
 Rules.mak                                          |  15 +
 extra/Configs/Config.csky                          |  25 ++
 extra/Configs/Config.in                            |   8 +
 extra/Configs/defconfigs/csky/defconfig            |   1 +
 include/elf.h                                      |  61 +++
 ldso/ldso/csky/dl-startup.h                        | 115 ++++++
 ldso/ldso/csky/dl-syscalls.h                       |   1 +
 ldso/ldso/csky/dl-sysdep.h                         |  89 +++++
 ldso/ldso/csky/elfinterp.c                         | 297 ++++++++++++++
 ldso/ldso/csky/read_tp.S                           |  17 +
 ldso/ldso/csky/resolve.S                           |  72 ++++
 libc/string/csky/Makefile                          |   6 +
 libc/string/csky/cskyv1/memcpy.S                   | 211 ++++++++++
 libc/string/csky/cskyv1/strcmp.S                   | 185 +++++++++
 libc/string/csky/cskyv1/strcpy.S                   | 139 +++++++
 libc/string/csky/cskyv2/abiv2_memcpy.S             | 184 +++++++++
 libc/string/csky/cskyv2/abiv2_strcmp.S             | 168 ++++++++
 libc/string/csky/cskyv2/abiv2_strcpy.S             | 129 ++++++
 libc/string/csky/cskyv2/macro.S                    |  13 +
 libc/string/csky/memcpy.S                          |   7 +
 libc/string/csky/strcmp.S                          |   7 +
 libc/string/csky/strcpy.S                          |   7 +
 libc/sysdeps/linux/common/posix_fadvise.c          |   2 +-
 libc/sysdeps/linux/common/posix_fadvise64.c        |   2 +-
 libc/sysdeps/linux/csky/Makefile                   |   6 +
 libc/sysdeps/linux/csky/Makefile.arch              |   6 +
 libc/sysdeps/linux/csky/__longjmp.S                |  39 ++
 libc/sysdeps/linux/csky/__syscall_error.c          |   9 +
 libc/sysdeps/linux/csky/bits/atomic.h              |  93 +++++
 libc/sysdeps/linux/csky/bits/endian.h              |  10 +
 libc/sysdeps/linux/csky/bits/fcntl.h               | 193 +++++++++
 libc/sysdeps/linux/csky/bits/fenv.h                |  58 +++
 libc/sysdeps/linux/csky/bits/kernel_stat.h         |  60 +++
 libc/sysdeps/linux/csky/bits/kernel_types.h        |  47 +++
 libc/sysdeps/linux/csky/bits/mathinline.h          | 445 +++++++++++++++++++++
 libc/sysdeps/linux/csky/bits/setjmp.h              |  19 +
 libc/sysdeps/linux/csky/bits/shm.h                 |  85 ++++
 libc/sysdeps/linux/csky/bits/sigcontextinfo.h      |  26 ++
 libc/sysdeps/linux/csky/bits/stackinfo.h           |   6 +
 libc/sysdeps/linux/csky/bits/syscalls.h            | 113 ++++++
 .../sysdeps/linux/csky/bits/uClibc_arch_features.h |  46 +++
 libc/sysdeps/linux/csky/bits/wordsize.h            |   1 +
 libc/sysdeps/linux/csky/cacheflush.c               |   2 +
 libc/sysdeps/linux/csky/clone.c                    |  47 +++
 libc/sysdeps/linux/csky/crt1.S                     |  95 +++++
 libc/sysdeps/linux/csky/crti.S                     |  13 +
 libc/sysdeps/linux/csky/crtn.S                     |  11 +
 libc/sysdeps/linux/csky/csky_clone.S               |  20 +
 libc/sysdeps/linux/csky/jmpbuf-unwind.h            |  15 +
 libc/sysdeps/linux/csky/libc-read_tp.S             |   1 +
 libc/sysdeps/linux/csky/setjmp.S                   |  43 ++
 libc/sysdeps/linux/csky/sys/cachectl.h             |  10 +
 libc/sysdeps/linux/csky/sys/procfs.h               | 126 ++++++
 libc/sysdeps/linux/csky/sys/ucontext.h             |  17 +
 libc/sysdeps/linux/csky/sys/user.h                 |  48 +++
 libc/sysdeps/linux/csky/sysdep.h                   | 204 ++++++++++
 libc/sysdeps/linux/csky/vfork.S                    |   6 +
 libpthread/nptl/sysdeps/csky/Makefile              |   6 +
 libpthread/nptl/sysdeps/csky/Makefile.arch         |   7 +
 libpthread/nptl/sysdeps/csky/dl-tls.h              |   9 +
 libpthread/nptl/sysdeps/csky/libc-tls.c            |  18 +
 libpthread/nptl/sysdeps/csky/pthread_spin_lock.S   |  18 +
 .../nptl/sysdeps/csky/pthread_spin_trylock.S       |  16 +
 libpthread/nptl/sysdeps/csky/pthreaddef.h          |  19 +
 libpthread/nptl/sysdeps/csky/tcb-offsets.sym       |  10 +
 libpthread/nptl/sysdeps/csky/tls.h                 | 170 ++++++++
 .../nptl/sysdeps/unix/sysv/linux/csky/Makefile     |   6 +
 .../sysdeps/unix/sysv/linux/csky/Makefile.arch     |   4 +
 .../unix/sysv/linux/csky/bits/pthreadtypes.h       | 181 +++++++++
 .../sysdeps/unix/sysv/linux/csky/bits/semaphore.h  |  35 ++
 .../sysdeps/unix/sysv/linux/csky/createthread.c    |   5 +
 .../nptl/sysdeps/unix/sysv/linux/csky/fork.c       |  31 ++
 .../sysdeps/unix/sysv/linux/csky/lowlevellock.h    | 281 +++++++++++++
 .../sysdeps/unix/sysv/linux/csky/pthread_once.c    | 100 +++++
 .../sysdeps/unix/sysv/linux/csky/sysdep-cancel.h   |  33 ++
 76 files changed, 4631 insertions(+), 2 deletions(-)
 create mode 100644 extra/Configs/Config.csky
 create mode 100644 extra/Configs/defconfigs/csky/defconfig
 create mode 100644 ldso/ldso/csky/dl-startup.h
 create mode 100644 ldso/ldso/csky/dl-syscalls.h
 create mode 100644 ldso/ldso/csky/dl-sysdep.h
 create mode 100644 ldso/ldso/csky/elfinterp.c
 create mode 100644 ldso/ldso/csky/read_tp.S
 create mode 100644 ldso/ldso/csky/resolve.S
 create mode 100644 libc/string/csky/Makefile
 create mode 100644 libc/string/csky/cskyv1/memcpy.S
 create mode 100644 libc/string/csky/cskyv1/strcmp.S
 create mode 100644 libc/string/csky/cskyv1/strcpy.S
 create mode 100644 libc/string/csky/cskyv2/abiv2_memcpy.S
 create mode 100644 libc/string/csky/cskyv2/abiv2_strcmp.S
 create mode 100644 libc/string/csky/cskyv2/abiv2_strcpy.S
 create mode 100644 libc/string/csky/cskyv2/macro.S
 create mode 100644 libc/string/csky/memcpy.S
 create mode 100644 libc/string/csky/strcmp.S
 create mode 100644 libc/string/csky/strcpy.S
 create mode 100644 libc/sysdeps/linux/csky/Makefile
 create mode 100644 libc/sysdeps/linux/csky/Makefile.arch
 create mode 100644 libc/sysdeps/linux/csky/__longjmp.S
 create mode 100644 libc/sysdeps/linux/csky/__syscall_error.c
 create mode 100644 libc/sysdeps/linux/csky/bits/atomic.h
 create mode 100644 libc/sysdeps/linux/csky/bits/endian.h
 create mode 100644 libc/sysdeps/linux/csky/bits/fcntl.h
 create mode 100644 libc/sysdeps/linux/csky/bits/fenv.h
 create mode 100644 libc/sysdeps/linux/csky/bits/kernel_stat.h
 create mode 100644 libc/sysdeps/linux/csky/bits/kernel_types.h
 create mode 100644 libc/sysdeps/linux/csky/bits/mathinline.h
 create mode 100644 libc/sysdeps/linux/csky/bits/setjmp.h
 create mode 100644 libc/sysdeps/linux/csky/bits/shm.h
 create mode 100644 libc/sysdeps/linux/csky/bits/sigcontextinfo.h
 create mode 100644 libc/sysdeps/linux/csky/bits/stackinfo.h
 create mode 100644 libc/sysdeps/linux/csky/bits/syscalls.h
 create mode 100644 libc/sysdeps/linux/csky/bits/uClibc_arch_features.h
 create mode 100644 libc/sysdeps/linux/csky/bits/wordsize.h
 create mode 100644 libc/sysdeps/linux/csky/cacheflush.c
 create mode 100644 libc/sysdeps/linux/csky/clone.c
 create mode 100644 libc/sysdeps/linux/csky/crt1.S
 create mode 100644 libc/sysdeps/linux/csky/crti.S
 create mode 100644 libc/sysdeps/linux/csky/crtn.S
 create mode 100644 libc/sysdeps/linux/csky/csky_clone.S
 create mode 100644 libc/sysdeps/linux/csky/jmpbuf-unwind.h
 create mode 100644 libc/sysdeps/linux/csky/libc-read_tp.S
 create mode 100644 libc/sysdeps/linux/csky/setjmp.S
 create mode 100644 libc/sysdeps/linux/csky/sys/cachectl.h
 create mode 100644 libc/sysdeps/linux/csky/sys/procfs.h
 create mode 100644 libc/sysdeps/linux/csky/sys/ucontext.h
 create mode 100644 libc/sysdeps/linux/csky/sys/user.h
 create mode 100644 libc/sysdeps/linux/csky/sysdep.h
 create mode 100644 libc/sysdeps/linux/csky/vfork.S
 create mode 100644 libpthread/nptl/sysdeps/csky/Makefile
 create mode 100644 libpthread/nptl/sysdeps/csky/Makefile.arch
 create mode 100644 libpthread/nptl/sysdeps/csky/dl-tls.h
 create mode 100644 libpthread/nptl/sysdeps/csky/libc-tls.c
 create mode 100644 libpthread/nptl/sysdeps/csky/pthread_spin_lock.S
 create mode 100644 libpthread/nptl/sysdeps/csky/pthread_spin_trylock.S
 create mode 100644 libpthread/nptl/sysdeps/csky/pthreaddef.h
 create mode 100644 libpthread/nptl/sysdeps/csky/tcb-offsets.sym
 create mode 100644 libpthread/nptl/sysdeps/csky/tls.h
 create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/Makefile
 create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/Makefile.arch
 create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/bits/pthreadtypes.h
 create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/bits/semaphore.h
 create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/createthread.c
 create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/fork.c
 create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/lowlevellock.h
 create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/pthread_once.c
 create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/sysdep-cancel.h

Comments

Waldemar Brodkorb Oct. 16, 2017, 5:12 p.m. | #1
Hi Guo,
Guo Ren wrote,

> Follow the steps to build c-sky uclibc linux system:
> 1. git clone https://github.com/c-sky/buildroot.git
> 2. cd buildroot
> 3. make qemu_csky_ck810_uclibc_defconfig
> 4. make
> 
> Follow the buildroot/board/qemu/csky/readme.txt to run.
> 
> This buildroot toolchain is pre-build, But you can rebuild
> the c-sky uclibc-ng alone and install it to the buildroot
> sysroot manually.
> 
> We'll try our best to improve the uclibc-ng continuously.

Thanks for the submission. Looks very good to me.
To finally test and push the patch I really need to create
a uClibc-ng toolchain on my own and I want to run the test-suite
on qemu or hardware.

I regulary run my testing shell script before releases
to minimize any regressions in common code.

I get following error when trying to create a toolchain with the
provided github sources for binutils, gcc and Linux kernel,
targeting ck610f CPU:
..
/pthread -I./libpthread/nptl/sysdeps/pthread/bits
-I./libpthread/nptl/sysdeps/generic -I./libc/sysdeps/linux/common
-isystem
/home/wbx/csky/toolchain_qemu-csky_uclibc-ng/usr/lib/gcc/csky-unknown-linux/6.3.0/include-fixed
-isystem
/home/wbx/csky/toolchain_qemu-csky_uclibc-ng/usr/lib/gcc/csky-unknown-linux/6.3.0/include
-I/home/wbx/csky/target_qemu-csky_uclibc-ng/usr/include/ -DNDEBUG
-DIN_LIB=libc -fPIC -MT libc/sysdeps/linux/csky/__syscall_error.os
-MD -MP -MF libc/sysdeps/linux/csky/.__syscall_error.os.dep
{standard input}: Assembler messages:
{standard input}: Error: value of 93939307125736 too large for field
of 4 bytes at 56
Makerules:369: die Regel für Ziel
„libc/sysdeps/linux/csky/__syscall_error.os“ scheiterte

Anything missing in the github sources required to actually build
a uClibc-ng toolchain from scratch?

Thanks in advance,
 Waldemar
Guo Ren Oct. 17, 2017, 8:19 a.m. | #2
On Mon, Oct 16, 2017 at 07:12:31PM +0200, Waldemar Brodkorb wrote:
Hi, Waldemar 
> I get following error when trying to create a toolchain with the
> provided github sources for binutils, gcc and Linux kernel,
> targeting ck610f CPU:
> ..
> /pthread -I./libpthread/nptl/sysdeps/pthread/bits
> -I./libpthread/nptl/sysdeps/generic -I./libc/sysdeps/linux/common
> -isystem
> /home/wbx/csky/toolchain_qemu-csky_uclibc-ng/usr/lib/gcc/csky-unknown-linux/6.3.0/include-fixed
> -isystem
> /home/wbx/csky/toolchain_qemu-csky_uclibc-ng/usr/lib/gcc/csky-unknown-linux/6.3.0/include
> -I/home/wbx/csky/target_qemu-csky_uclibc-ng/usr/include/ -DNDEBUG
> -DIN_LIB=libc -fPIC -MT libc/sysdeps/linux/csky/__syscall_error.os
> -MD -MP -MF libc/sysdeps/linux/csky/.__syscall_error.os.dep
> {standard input}: Assembler messages:
> {standard input}: Error: value of 93939307125736 too large for field
> of 4 bytes at 56
> Makerules:369: die Regel für Ziel
> „libc/sysdeps/linux/csky/__syscall_error.os“ scheiterte
> 
> Anything missing in the github sources required to actually build
> a uClibc-ng toolchain from scratch?

Seems assembler failed.

Could you send me your config.log for binutils & gcc?

Best Regards
 Guo Ren
Waldemar Brodkorb Oct. 17, 2017, 6:08 p.m. | #3
Hi Guo,
Guo Ren wrote,

> > {standard input}: Assembler messages:
> > {standard input}: Error: value of 93939307125736 too large for field
> > of 4 bytes at 56
> > Makerules:369: die Regel für Ziel
> > „libc/sysdeps/linux/csky/__syscall_error.os“ scheiterte
> > 
> > Anything missing in the github sources required to actually build
> > a uClibc-ng toolchain from scratch?
> 
> Seems assembler failed.
> 
> Could you send me your config.log for binutils & gcc?

All config.log files and the complete build ouput:
https://debug.openadk.org/csky/

best regards
 Waldemar

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 642f903..d5aa024 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7,6 +7,9 @@  ARC:
 Alexey Brodkin <Alexey.Brodkin@synopsys.com>
 Vineet Gupta <Vineet.Gupta1@synopsys.com>
 
+CSKY:
+Guo Ren <ren_guo@c-sky.com>
+
 MIPS:
 Matthew Fortune <Matthew.Fortune@imgtec.com>
 
diff --git a/Rules.mak b/Rules.mak
index 0aa29a7..b553cd4 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -453,6 +453,21 @@  ifeq ($(TARGET_ARCH),cris)
 	PIEFLAG_NAME:=-fpie
 endif
 
+ifeq ($(TARGET_ARCH),csky)
+	# In csky gas implement, we use $t and $d to detect .text or literal pool.
+	# So we couldn't strip them for objdump.
+	STRIP_FLAGS += -K "$$"t -K "$$"d
+
+	CPU_CFLAGS-$(CK610)	+= -mcpu=ck610f
+	CPU_CFLAGS-$(CK810)	+= -mcpu=ck810f
+	CPU_CFLAGS-$(CK807)	+= -mcpu=ck807f
+
+	CPU_CFLAGS-$(UCLIBC_HAS_FPU)		+= -mhard-float
+
+	CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN)	+= -mlittle-endian
+	CPU_CFLAGS-$(ARCH_BIG_ENDIAN)		+= -mbig-endian
+endif
+
 ifeq ($(TARGET_ARCH),m68k)
 	# -fPIC is only supported for 68020 and above.  It is not supported
 	# for 68000, 68010, or Coldfire.
diff --git a/extra/Configs/Config.csky b/extra/Configs/Config.csky
new file mode 100644
index 0000000..704f7be
--- /dev/null
+++ b/extra/Configs/Config.csky
@@ -0,0 +1,25 @@ 
+config TARGET_ARCH
+	string
+	default "csky"
+
+config FORCE_OPTIONS_FOR_ARCH
+	bool
+	default y
+	select ARCH_ANY_ENDIAN
+	select ARCH_HAS_DEPRECATED_SYSCALLS
+	select ARCH_USE_MMU
+	select ARCH_HAS_MMU
+
+choice
+	prompt "Target Processor Type"
+	default CK610
+
+config CK610
+	bool "ck610"
+config CK810
+	bool "ck810"
+config CK807
+	bool "ck807"
+
+endchoice
+
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index ce832b5..b5ee294 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -22,6 +22,7 @@  choice
 	default TARGET_avr32 if DESIRED_TARGET_ARCH = "avr32"
 	default TARGET_bfin if DESIRED_TARGET_ARCH = "bfin"
 	default TARGET_cris if DESIRED_TARGET_ARCH = "cris"
+	default TARGET_csky if DESIRED_TARGET_ARCH = "csky"
 	default TARGET_frv if DESIRED_TARGET_ARCH = "frv"
 	default TARGET_h8300 if DESIRED_TARGET_ARCH = "h8300"
 	default TARGET_hppa if DESIRED_TARGET_ARCH = "hppa"
@@ -70,6 +71,9 @@  config TARGET_c6x
 config TARGET_cris
 	bool "cris"
 
+config TARGET_csky
+	bool "csky"
+
 config TARGET_frv
 	bool "frv"
 
@@ -156,6 +160,10 @@  if TARGET_cris
 source "extra/Configs/Config.cris"
 endif
 
+if TARGET_csky
+source "extra/Configs/Config.csky"
+endif
+
 if TARGET_frv
 source "extra/Configs/Config.frv"
 endif
diff --git a/extra/Configs/defconfigs/csky/defconfig b/extra/Configs/defconfigs/csky/defconfig
new file mode 100644
index 0000000..da837fc
--- /dev/null
+++ b/extra/Configs/defconfigs/csky/defconfig
@@ -0,0 +1 @@ 
+TARGET_csky=y
diff --git a/include/elf.h b/include/elf.h
index c8488bb..fcb546a 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -1200,6 +1200,67 @@  typedef struct
 #define ELF64_M_SIZE(info)	ELF32_M_SIZE (info)
 #define ELF64_M_INFO(sym, size)	ELF32_M_INFO (sym, size)
 
+/* C-SKY relocs. */
+
+#define R_CKCORE_NONE               0
+#define R_CKCORE_ADDR32             1
+#define R_CKCORE_PCRELIMM8BY4       2
+#define R_CKCORE_PCRELIMM11BY2      3
+#define R_CKCORE_PCRELIMM4BY2       4
+#define R_CKCORE_PCREL32            5
+#define R_CKCORE_PCRELJSR_IMM11BY2  6
+#define R_CKCORE_GNU_VTINHERIT      7
+#define R_CKCORE_GNU_VTENTRY        8
+#define R_CKCORE_RELATIVE           9
+#define R_CKCORE_COPY               10
+#define R_CKCORE_GLOB_DAT           11
+#define R_CKCORE_JUMP_SLOT          12
+#define R_CKCORE_GOTOFF             13
+#define R_CKCORE_GOTPC              14
+#define R_CKCORE_GOT32              15
+#define R_CKCORE_PLT32              16
+#define R_CKCORE_ADDRGOT            17
+#define R_CKCORE_ADDRPLT            18
+#define R_CKCORE_PCREL_IMM26BY2     19
+#define R_CKCORE_PCREL_IMM16BY2     20
+#define R_CKCORE_PCREL_IMM16BY4     21
+#define R_CKCORE_PCREL_IMM10BY2     22
+#define R_CKCORE_PCREL_IMM10BY4     23
+#define R_CKCORE_ADDR_HI16          24
+#define R_CKCORE_ADDR_LO16          25
+#define R_CKCORE_GOTPC_HI16         26
+#define R_CKCORE_GOTPC_LO16         27
+#define R_CKCORE_GOTOFF_HI16        28
+#define R_CKCORE_GOTOFF_LO16        29
+#define R_CKCORE_GOT12              30
+#define R_CKCORE_GOT_HI16           31
+#define R_CKCORE_GOT_LO16           32
+#define R_CKCORE_PLT12              33
+#define R_CKCORE_PLT_HI16           34
+#define R_CKCORE_PLT_LO16           35
+#define R_CKCORE_ADDRGOT_HI16       36
+#define R_CKCORE_ADDRGOT_LO16       37
+#define R_CKCORE_ADDRPLT_HI16       38
+#define R_CKCORE_ADDRPLT_LO16       39
+#define R_CKCORE_PCREL_JSR_IMM26BY2 40
+#define R_CKCORE_TOFFSET_LO16       41
+#define R_CKCORE_DOFFSET_LO16       42
+#define R_CKCORE_PCREL_IMM18BY2     43
+#define R_CKCORE_DOFFSET_IMM18      44
+#define R_CKCORE_DOFFSET_IMM18BY2   45
+#define R_CKCORE_DOFFSET_IMM18BY4   46
+#define R_CKCORE_GOTOFF_IMM18       47
+#define R_CKCORE_GOT_IMM18BY4       48
+#define R_CKCORE_PLT_IMM18BY4       49
+#define R_CKCORE_PCREL_IMM7BY4      50
+#define R_CKCORE_TLS_LE32           51
+#define R_CKCORE_TLS_IE32           52
+#define R_CKCORE_TLS_GD32           53
+#define R_CKCORE_TLS_LDM32          54
+#define R_CKCORE_TLS_LDO32          55
+#define R_CKCORE_TLS_DTPMOD32       56
+#define R_CKCORE_TLS_DTPOFF32       57
+#define R_CKCORE_TLS_TPOFF32        58
 
 /* Motorola 68k specific definitions.  */
 
diff --git a/ldso/ldso/csky/dl-startup.h b/ldso/ldso/csky/dl-startup.h
new file mode 100644
index 0000000..0a74ab6
--- /dev/null
+++ b/ldso/ldso/csky/dl-startup.h
@@ -0,0 +1,115 @@ 
+#ifdef __CSKYABIV2__
+
+__asm__ (
+    "    .text\n\t"
+    "    .globl _start\n\t"
+    "_start:\n\t"
+    "    mov a0, sp\n\t"
+    "    bsr _dl_start\n\t"
+    "    # Return from _dl_start, user entry point address in a0 \n\t"
+    "    # the code is PIC, so get global offset table\n\t"
+    "    grs gb,.Lgetpc1\n\t"
+    ".Lgetpc1:\n\t    "
+    "    lrw t0, .Lgetpc1@GOTPC\n\t"
+    "    add gb, gb,t0\n\t"
+    "    lrw r5, _dl_skip_args@GOT\n\t"
+    "    ldr.w r5, (gb, r5 << 0)\n\t"
+    "    # get the value of variable _dl_skip_args in r6\n\t"
+    "    ldw r6, (r5, 0)\n\t"
+    "    # get the argc in r7 \n\t"
+    "    ldw r7, (sp, 0)\n\t"
+    "    # adjust the argc, this may be a bug when _dl_skip_args > argc\n\t"
+    "    rsub r6, r7\n\t"
+    "    # adjust the stack\n\t"
+    "    mov r7, r6\n\t"
+    "    lsli r6, 2\n\t"
+    "    # adjust the stack pointer,this may be a bug, "
+    "    # because it must be 8 bytes align"
+    "    addu sp, r6\n\t"
+    "    stw  r7, (sp, 0)\n\t"
+    "    lrw  r7, _dl_fini@GOTOFF\n\t"
+    "    addu  r7, gb\n\t"
+    "    jmp a0"
+);
+#else
+__asm__ (
+    "    .text\n\t"
+    "    .globl _start\n\t"
+    "_start:\n\t"
+    "    mov r2, r0\n\t"
+# if defined(__ck810__)
+    "    bsr _dl_start\n\t"
+#else
+    "    # the code is PIC, so get global offset table\n\t"
+    "    bsr .Lgetpc0\n\t"
+    ".Lgetpc0:\n\t    "
+    "    lrw r14, .Lgetpc0@GOTPC\n\t"
+    "    add r14, r15\n\t"
+    "    lrw r4, _dl_start@GOTOFF\n\t"
+    "    add r4, r14\n\t"
+    "    jsr r4\n\t"
+#endif
+    "    # Return from _dl_start, user entry point address in r2 \n\t"
+    "    # the code is PIC, so get global offset table\n\t"
+    "    bsr .Lgetpc1\n\t"
+    ".Lgetpc1:\n\t    "
+    "    lrw r3, .Lgetpc1@GOTPC\n\t"
+    "    add r3, r15\n\t"
+# if defined(__ck810__)
+    "    ldw r5, (r3, _dl_skip_args@GOT)\n\t"
+#else
+    "    lrw r4, _dl_skip_args@GOT\n\t"
+    "    add r4, r3\n\t"
+    "    ldw r5, (r4, 0)\n\t"
+#endif
+    "    # get the value of variable _dl_skip_args in r6\n\t"
+    "    ldw r6, (r5, 0)\n\t"
+    "    # get the argc in r7 \n\t"
+    "    ldw r7, (r0, 0)\n\t"
+    "    # adjust the argc, this may be a bug when _dl_skip_args > argc\n\t"
+    "    rsub r6, r7\n\t"
+    "    # adjust the stack\n\t"
+    "    mov r7, r6\n\t"
+    "    lsli r6, 2\n\t"
+    "    # adjust the stack pointer,this may be a bug, "
+    "    # because it must be 8 bytes align"
+    "    addu r0, r6\n\t"
+    "    stw  r7, (r0, 0)\n\t"
+    "    lrw  r7, _dl_fini@GOTOFF\n\t"
+    "    addu  r7, r3\n\t"
+    "    jmp r2"
+);
+
+#endif
+
+/* Get a pointer to the argv array. */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1)
+
+/* Function calls are not safe until the GOT relocations have been done.  */
+#define NO_FUNCS_BEFORE_BOOTSTRAP
+/* Handle relocation of the symbols in the dynamic loader. */
+static __always_inline
+void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
+    unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab)
+{
+    switch (ELF32_R_TYPE(rpnt->r_info))
+    {
+       case R_CKCORE_RELATIVE:
+            *reloc_addr = load_addr + rpnt->r_addend;
+            break;
+        case R_CKCORE_GLOB_DAT:
+        case R_CKCORE_JUMP_SLOT:
+            *reloc_addr = symbol_addr;
+            break;
+        case R_CKCORE_ADDR32:
+            *reloc_addr = symbol_addr + rpnt->r_addend;
+            break;
+        case R_CKCORE_NONE:
+            break;
+
+        default:
+            _dl_exit(1);
+    }
+}
+
+
diff --git a/ldso/ldso/csky/dl-syscalls.h b/ldso/ldso/csky/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ldso/ldso/csky/dl-syscalls.h
@@ -0,0 +1 @@ 
+/* stub for arch-specific syscall issues */
diff --git a/ldso/ldso/csky/dl-sysdep.h b/ldso/ldso/csky/dl-sysdep.h
new file mode 100644
index 0000000..c78dd81
--- /dev/null
+++ b/ldso/ldso/csky/dl-sysdep.h
@@ -0,0 +1,89 @@ 
+/* Define this if the system uses RELOCA.  */
+#define ELF_USES_RELOCA
+
+#include <elf.h>
+/* Initialization sequence for the GOT.  */
+#define INIT_GOT(GOT_BASE,MODULE)                           \
+do {                                                        \
+    GOT_BASE[2] = (unsigned long) _dl_linux_resolve;        \
+    GOT_BASE[1] = (unsigned long) MODULE;                   \
+} while(0)
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_MCORE
+#undef  MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "csky"
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+/* 65536 bytes alignment */
+#define PAGE_ALIGN 0xfffff000          /* need modify */
+#define ADDR_ALIGN 0xfff
+#define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+   TLS variable, so undefined references should not be allowed to
+   define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_CKCORE_JUMP_SLOT || (type) == R_CKCORE_TLS_DTPMOD32 \
+     || (type) == R_CKCORE_TLS_DTPOFF32 || (type) == R_CKCORE_TLS_TPOFF32) \
+     * ELF_RTYPE_CLASS_PLT)                 \
+   | (((type) == R_CKCORE_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
+   first element of the GOT.  This must be inlined in a function which
+   uses global data.  */
+static __inline__ Elf32_Addr elf_machine_dynamic (void) attribute_unused;
+static __inline__ Elf32_Addr
+elf_machine_dynamic (void)
+{
+    register Elf32_Addr *got __asm__ ("gb");    /* need modify */
+    return *got;
+}
+
+/* this funtion will be called only when the auxvt[AT_BASE].a_un.a_val == 0
+   so it normal not be called, we should define a default address of the interprrter load */
+static __inline__ Elf32_Addr elf_machine_load_address (void) attribute_unused;
+static __inline__ Elf32_Addr
+elf_machine_load_address (void)
+{
+#ifdef __CSKYABIV2__
+  extern Elf32_Addr internal_function __dl_start (void *) __asm__ ("_dl_start");
+  Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
+  Elf32_Addr pcrel_addr;
+  __asm__  ("grs %0,_dl_start\n" : "=r" (pcrel_addr));
+#else
+  extern Elf32_Addr internal_function __start_flag (void *) __asm__ ("start_flag");
+  Elf32_Addr got_addr = (Elf32_Addr) &__start_flag;
+  Elf32_Addr pcrel_addr;
+  __asm__  ("subi sp,8\n"           \
+        "stw lr,(sp,0)\n"               \
+        "bsr start_flag\n"              \
+        "start_flag:"                           \
+        "mov  %0, lr\n"         \
+        "ldw lr,(sp,0)\n"       \
+        "addi sp,8\n"           \
+        : "=r" (pcrel_addr));
+#endif
+  return pcrel_addr - got_addr;
+
+}
+
+/* some relocation information are machine special */
+static __inline__ void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+              Elf32_Word relative_count)
+{
+    Elf32_Rela *rpnt = (void *) rel_addr;
+    --rpnt;
+    do {
+        Elf32_Addr *reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
+        *reloc_addr = load_off + rpnt->r_addend;
+    } while (--relative_count); /* maybe need modify */
+}
+
diff --git a/ldso/ldso/csky/elfinterp.c b/ldso/ldso/csky/elfinterp.c
new file mode 100644
index 0000000..1469c28
--- /dev/null
+++ b/ldso/ldso/csky/elfinterp.c
@@ -0,0 +1,297 @@ 
+#include "ldso.h"
+
+unsigned long
+_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+    ELF_RELOC *this_reloc;
+    int symtab_index;
+    //char *rel_tab;
+    Elf32_Sym *sym_tab;
+    char *str_tab;
+    char *sym_name;
+    char *sym_addr;
+    char **reloc_addr;
+
+    this_reloc  = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL];
+    this_reloc += reloc_entry;
+    //this_reloc = (ELF_RELOC *)(intptr_t)(rel_tab + reloc_entry);
+    symtab_index = ELF32_R_SYM(this_reloc->r_info);
+
+    sym_tab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+    str_tab = (char *)tpnt->dynamic_info[DT_STRTAB];
+    sym_name = str_tab + sym_tab[symtab_index].st_name;
+
+    reloc_addr = (char **)((unsigned long)this_reloc->r_offset +
+                     (unsigned long)tpnt->loadaddr);
+
+    sym_addr = _dl_find_hash(sym_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+
+    if (unlikely(!sym_addr)) {
+        _dl_dprintf(2, "%s: 1can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, sym_name, tpnt->libname);
+        _dl_exit(1);
+    }
+
+    *reloc_addr = sym_addr;
+
+    return (unsigned long)sym_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem*scope,
+      unsigned long rel_addr, unsigned long rel_size,
+      int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem*scope,
+               ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
+{
+    unsigned int i;
+    char *strtab;
+    Elf32_Sym *symtab;
+    ELF_RELOC *rpnt;
+    int symtab_index;
+
+    /* Parse the relocation information. */
+    rpnt = (ELF_RELOC *)(intptr_t)rel_addr;
+    rel_size /= sizeof(ELF_RELOC);
+    symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+    strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+    for (i = 0; i < rel_size; i++, rpnt++) {
+        int res;
+
+        symtab_index = ELF32_R_SYM(rpnt->r_info);
+
+        debug_sym(symtab, strtab, symtab_index);
+        debug_reloc(symtab, strtab, rpnt);
+
+        res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
+        if (res == 0)
+            continue;
+        _dl_dprintf(2, "\n%s: ", _dl_progname);
+
+        if (symtab_index)
+            _dl_dprintf(2, "symbol '%s': ",
+                    strtab + symtab[symtab_index].st_name);
+        if (unlikely(res < 0)) {
+            int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+            _dl_dprintf(2, "2can't handle reloc type '%s' in lib '%s'\n",
+                    _dl_reltypes(reloc_type), tpnt->libname);
+#else
+            _dl_dprintf(2, "3can't handle reloc type %x in lib '%s'\n",
+                    reloc_type, tpnt->libname);
+#endif
+            return res;
+        } else if (unlikely(res > 0)) {
+            _dl_dprintf(2, "4can't resolve symbol in lib '%s'.\n", tpnt->libname);
+            return res;
+        }
+    }
+
+    return 0;
+}
+
+static int
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+         ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
+{
+    int reloc_type;
+    int symtab_index;
+    char *symname;
+    unsigned long *reloc_addr;
+    unsigned long symbol_addr;
+    struct symbol_ref sym_ref;
+#if defined (__SUPPORT_LD_DEBUG__)
+    unsigned long old_val;
+#endif
+#if defined USE_TLS && USE_TLS
+	struct elf_resolve *tls_tpnt = NULL;
+#endif
+#if defined(__CSKYABIV2__)
+    unsigned int insn_opcode = 0x0;
+    unsigned short *opcode16_addr;
+#endif
+
+    reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+#if defined(__CSKYABIV2__)
+    opcode16_addr = (unsigned short *)reloc_addr;
+#endif
+	reloc_type = ELF32_R_TYPE(rpnt->r_info);
+
+	if (reloc_type == R_CKCORE_NONE)
+		return 0;
+
+    symtab_index = ELF32_R_SYM(rpnt->r_info);
+    symbol_addr = 0;
+    sym_ref.sym = &symtab[symtab_index];
+    sym_ref.tpnt = NULL;
+    symname = strtab + symtab[symtab_index].st_name;
+    if (symtab_index) {
+        symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt,
+                               elf_machine_type_class(reloc_type), &sym_ref);
+    /*
+         * We want to allow undefined references to weak symbols - this
+         * might have been intentional.  We should not be linking local
+         * symbols here, so all bases should be covered.
+         */
+      //  if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
+		if (!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
+			&& (ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
+            return 1;
+#if defined USE_TLS && USE_TLS
+		tls_tpnt = sym_ref.tpnt;
+#endif
+    }else{
+		/*
+		 * Relocs against STN_UNDEF are usually treated as using a
+		 * symbol value of zero, and using the module containing the
+		 * reloc itself.
+		 */
+        symbol_addr = symtab[symtab_index].st_name;
+#if defined USE_TLS && USE_TLS
+		tls_tpnt = tpnt;
+#endif
+    }
+#if defined (__SUPPORT_LD_DEBUG__)
+    old_val = *reloc_addr;
+#endif
+
+    switch (reloc_type) {            /* need modify */
+        case R_CKCORE_NONE:
+		case R_CKCORE_PCRELJSR_IMM11BY2:
+            break;
+        case R_CKCORE_ADDR32:
+            *reloc_addr = symbol_addr + rpnt->r_addend;
+            break;
+        case R_CKCORE_GLOB_DAT:
+        case R_CKCORE_JUMP_SLOT:
+            *reloc_addr = symbol_addr;
+            break;
+        case R_CKCORE_RELATIVE:
+            *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
+            break;
+#if defined(__CSKYABIV2__)
+        case R_CKCORE_ADDR_HI16:
+            insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1));
+            insn_opcode = (insn_opcode & 0xffff0000)
+                            | (((symbol_addr + rpnt->r_addend) >> 16) & 0xffff);
+            *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16);
+            *opcode16_addr = (unsigned short)(insn_opcode & 0xffff);
+            break;
+        case R_CKCORE_ADDR_LO16:
+            insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1));
+            insn_opcode = (insn_opcode & 0xffff0000)
+                            | ((symbol_addr + rpnt->r_addend) & 0xffff);
+            *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16);
+            *opcode16_addr = (unsigned short)(insn_opcode & 0xffff);
+            break;
+        case R_CKCORE_PCREL_IMM26BY2:
+        {
+            unsigned int offset = ((symbol_addr + rpnt->r_addend -
+                                    (unsigned int)reloc_addr) >> 1);
+            insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1));
+            if (offset > 0x3ffffff){
+                _dl_dprintf(2, "%s:The reloc R_CKCORE_PCREL_IMM26BY2 cannot reach the symbol '%s'.\n", _dl_progname, symname);
+                _dl_exit(1);
+            }
+            insn_opcode = (insn_opcode & ~0x3ffffff) | offset;
+            *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16);
+            *opcode16_addr = (unsigned short)(insn_opcode & 0xffff);
+            break;
+        }
+        case R_CKCORE_PCREL_JSR_IMM26BY2:
+            break;
+#endif
+        case R_CKCORE_COPY:
+            if (symbol_addr) {
+#if defined (__SUPPORT_LD_DEBUG__)
+                if (_dl_debug_move)
+                    _dl_dprintf(_dl_debug_file,
+                            "\n%s move %d bytes from %x to %x",
+                            symname, symtab[symtab_index].st_size,
+                            symbol_addr, reloc_addr);
+#endif
+
+                _dl_memcpy((char *)reloc_addr,
+                       (char *)symbol_addr,
+                       symtab[symtab_index].st_size);
+            }
+            break;
+#if defined USE_TLS && USE_TLS
+		case R_CKCORE_TLS_DTPMOD32:
+			*reloc_addr = tls_tpnt->l_tls_modid;
+			break;
+		case R_CKCORE_TLS_DTPOFF32:
+			*reloc_addr += symbol_addr;
+			break;
+		case R_CKCORE_TLS_TPOFF32:
+			CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
+			*reloc_addr += tls_tpnt->l_tls_offset + symbol_addr;
+			break;
+#endif
+        default:
+            return -1;
+    }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+    if (_dl_debug_reloc && _dl_debug_detail)
+        _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x",
+                old_val, *reloc_addr, reloc_addr);
+#endif
+
+    return 0;
+}
+
+static int
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+          ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
+{
+    int reloc_type;
+    unsigned long *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+    unsigned long old_val;
+#endif
+
+    reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+    reloc_type = ELF32_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+    old_val = *reloc_addr;
+#endif
+
+    switch (reloc_type) {
+        case R_CKCORE_NONE:
+		case R_CKCORE_PCRELJSR_IMM11BY2:
+            break;
+        case R_CKCORE_JUMP_SLOT:
+            *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
+            break;
+        default:
+            return -1;
+    }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+    if (_dl_debug_reloc && _dl_debug_detail)
+        _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x",
+                old_val, *reloc_addr, reloc_addr);
+#endif
+
+    return 0;
+}
+
+
+void
+_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+                      unsigned long rel_addr,
+                      unsigned long rel_size)
+{
+    (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information(struct dyn_elf *rpnt,
+                 struct r_scope_elem *scope,
+                 unsigned long rel_addr,
+                 unsigned long rel_size)
+{
+    return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
diff --git a/ldso/ldso/csky/read_tp.S b/ldso/ldso/csky/read_tp.S
new file mode 100644
index 0000000..ef8d509
--- /dev/null
+++ b/ldso/ldso/csky/read_tp.S
@@ -0,0 +1,17 @@ 
+#include <sysdep.h>
+
+#ifndef NOT_IN_libc
+.global __read_tp
+#else
+.hidden __read_tp
+#endif
+
+ENTRY (__read_tp)
+#ifdef __CSKYABIV2__
+	mov	a0, tls
+#else
+	trap 3
+#endif
+	rts
+END (__read_tp)
+
diff --git a/ldso/ldso/csky/resolve.S b/ldso/ldso/csky/resolve.S
new file mode 100644
index 0000000..46a4363
--- /dev/null
+++ b/ldso/ldso/csky/resolve.S
@@ -0,0 +1,72 @@ 
+/*
+ * This function is not called directly. It is jumped when attempting to use a
+ * symbol that has not yet been resolved.
+ *
+ *.plt*:
+ *   subi r0, 32
+ *   stw r2, (r0, 0)
+ *   stw r3, (r0, 4)
+ *   lrw r3, #offset
+ *   ldw r2, (gb, 8)
+ *   jmp r2
+ */
+
+.import _dl_linux_resolver
+
+.text
+.globl _dl_linux_resolve
+.type  _dl_linux_resolve,@function
+
+_dl_linux_resolve:
+#ifdef __CSKYABIV1__
+    stw  r4, (r0, 8)
+    stw  r5, (r0, 12)
+    stw  r6, (r0, 16)
+    stw  r7, (r0, 20)
+    stw  r15,(r0, 24)
+    # load the ID of this module
+    ldw  r2, (gb, 4)
+    # r2 = id, r3 = offset(do it in plt*)
+#ifdef __PIC__
+    # get global offset table address_
+    bsr .L2
+.L2:
+    lrw r7, .L2@GOTPC
+    add r7, r15
+    # get the address of function (_dl_linux_resolver) in got table
+    lrw r6, _dl_linux_resolver@GOT
+    add r6, r7
+    ldw r5, (r6, 0)
+    jsr r5
+#else  /* no __PIC__ */
+    jsri  _dl_linux_resolver      /* need modify */
+#endif
+    # Return from _dl_linux_resolver, the address of function is in r2
+    mov  r1, r2
+    # Restore the registers
+    ldw  r2, (r0, 0)
+    ldw  r3, (r0, 4)
+    ldw  r4, (r0, 8)
+    ldw  r5, (r0, 12)
+    ldw  r6, (r0, 16)
+    ldw  r7, (r0, 20)
+    ldw  r15,(r0, 24)
+    # Restore the r0, because r0 is subtracted in PLT table
+    addi r0, 32
+    # The address of function is in r1, call the function without saving pc
+    jmp  r1
+#else       /* __CSKYABIV1__ */
+    subi sp, 20
+    stm  a0-a3, (sp)
+    stw  lr, (sp, 16)
+    # a0 = id, a1 = offset(do it in plt*)
+    ldw  a0,  (gb, 4)
+    mov  a1, t1
+    bsr  _dl_linux_resolver
+    mov  t0, a0
+    ldw  lr, (sp, 16)
+    ldm  a0-a3, (sp)
+    addi sp, 20
+    jmp  t0
+
+#endif
diff --git a/libc/string/csky/Makefile b/libc/string/csky/Makefile
new file mode 100644
index 0000000..ce5add6
--- /dev/null
+++ b/libc/string/csky/Makefile
@@ -0,0 +1,6 @@ 
+top_srcdir:=../../../
+top_builddir:=../../../
+all: objs
+include $(top_builddir)Rules.mak
+include ../Makefile.in
+include $(top_srcdir)Makerules
diff --git a/libc/string/csky/cskyv1/memcpy.S b/libc/string/csky/cskyv1/memcpy.S
new file mode 100644
index 0000000..dfa7f64
--- /dev/null
+++ b/libc/string/csky/cskyv1/memcpy.S
@@ -0,0 +1,211 @@ 
+.macro      GET_FRONT_BITS rx ry
+#ifdef      __cskyLE__
+    lsr     \rx, \ry
+#else
+    lsl     \rx, \ry
+#endif
+.endm
+
+.macro      GET_AFTER_BITS rx ry
+#ifdef      __cskyLE__
+    lsl     \rx, \ry
+#else
+    lsr     \rx, \ry
+#endif
+.endm
+
+
+#ifdef WANT_WIDE
+# define Wmemcpy wmemcpy
+#else
+# define Wmemcpy memcpy
+#endif
+
+/* void *memcpy(void *dest, const void *src, size_t n); */
+
+	.text
+	.align 2
+	.global Wmemcpy
+	.type   Wmemcpy, @function
+Wmemcpy:
+    mov     r7, r2
+    cmplti  r4, 4                                   /* If len less than 4 bytes */
+    jbt     .L_copy_by_byte
+
+    mov     r6, r2
+    andi    r6, 3
+    cmpnei  r6, 0
+    jbt     .L_dest_not_aligned                     /* If dest is not 4 bytes aligned */
+.L0:
+    mov     r6, r3
+    andi    r6, 3
+    cmpnei  r6, 0
+    jbt     .L_dest_aligned_but_src_not_aligned     /* If dest is aligned, but src is not aligned */
+
+    cmplti  r4, 16                                  /* dest and src are all aligned */
+    jbt     .L_aligned_and_len_less_16bytes         /* If len less than 16 bytes */
+
+    subi    sp, 8
+    stw     r8, (sp, 0)
+    stw     r9, (sp, 4)
+.L_aligned_and_len_larger_16bytes:                  /* src and dst are all aligned, and len > 16 bytes */
+    ldw     r1, (r3, 0)
+    ldw     r5, (r3, 4)
+    ldw     r8, (r3, 8)
+    ldw     r9, (r3, 12)
+    stw     r1, (r7, 0)
+    stw     r5, (r7, 4)
+    stw     r8, (r7, 8)
+    stw     r9, (r7, 12)
+    subi    r4, 16
+    addi    r3, 16
+    addi    r7, 16
+    cmplti  r4, 16
+    jbf     .L_aligned_and_len_larger_16bytes
+    ldw     r8, (sp, 0)
+    ldw     r9, (sp, 4)
+    addi    sp, 8
+
+.L_aligned_and_len_less_16bytes:
+    cmplti  r4, 4
+    jbt     .L_copy_by_byte
+    ldw     r1, (r3, 0)
+    stw     r1, (r7, 0)
+    subi    r4, 4
+    addi    r3, 4
+    addi    r7, 4
+    jbr     .L_aligned_and_len_less_16bytes
+
+.L_copy_by_byte:                                    /* len less than 4 bytes */
+    cmpnei  r4, 0
+    jbf     .L_return
+    ldb     r1, (r3, 0)
+    stb     r1, (r7, 0)
+    subi    r4, 1
+    addi    r3, 1
+    addi    r7, 1
+    jbr     .L_copy_by_byte
+
+.L_return:
+    rts
+
+/* If dest is not aligned, we copy some bytes to make dest align.
+   Then we should judge whether src is aligned. */
+
+.L_dest_not_aligned:
+    mov     r5, r3                                  /* consider overlapped case */
+    rsub    r5, r5, r7
+    abs     r5, r5
+    cmplt   r5, r4
+    jbt     .L_copy_by_byte
+
+.L1:
+    ldb     r1, (r3, 0)                             /* makes the dest align. */
+    stb     r1, (r7, 0)
+    addi    r6, 1
+    subi    r4, 1
+    addi    r3, 1
+    addi    r7, 1
+    cmpnei  r6, 4
+    jbt     .L1
+    cmplti  r4, 4
+    jbt     .L_copy_by_byte
+    jbf     .L0                                     /* judge whether the src is aligned. */
+
+.L_dest_aligned_but_src_not_aligned:
+    mov     r5, r3                                  /* consider overlapped case*/
+    rsub    r5, r5, r7
+    abs     r5, r5
+    cmplt   r5, r4
+    jbt     .L_copy_by_byte
+
+    bclri   r3, 0
+    bclri   r3, 1
+    ldw     r1, (r3, 0)
+    addi    r3, 4
+
+    subi    sp, 16
+    stw     r11, (sp,0)
+    stw     r12, (sp,4)
+    stw     r13, (sp,8)
+    movi    r5, 8
+    mult    r5, r6                                  /* r6 is used to store tne misaligned bits */
+    mov     r12, r5
+    rsubi   r5, 31
+    addi    r5, 1
+    mov     r13, r5
+
+    cmplti  r4, 16
+    jbt     .L_not_aligned_and_len_less_16bytes
+
+    stw     r8, (sp, 12)
+    subi    sp, 8
+    stw     r9, (sp, 0)
+    stw     r10, (sp, 4)
+.L_not_aligned_and_len_larger_16bytes:
+    ldw     r5, (r3, 0)
+    ldw     r11, (r3, 4)
+    ldw     r8, (r3, 8)
+    ldw     r9, (r3, 12)
+
+    GET_FRONT_BITS r1 r12                          /* little or big endian? */
+    mov     r10, r5
+    GET_AFTER_BITS r5 r13
+    or      r5, r1
+
+    GET_FRONT_BITS r10 r12
+    mov     r1, r11
+    GET_AFTER_BITS r11 r13
+    or      r11, r10
+
+    GET_FRONT_BITS r1 r12
+    mov     r10, r8
+    GET_AFTER_BITS r8 r13
+    or      r8, r1
+
+    GET_FRONT_BITS r10 r12
+    mov     r1, r9
+    GET_AFTER_BITS r9 r13
+    or      r9, r10
+
+    stw     r5, (r7, 0)
+    stw     r11, (r7, 4)
+    stw     r8, (r7, 8)
+    stw     r9, (r7, 12)
+    subi    r4, 16
+    addi    r3, 16
+    addi    r7, 16
+    cmplti  r4, 16
+    jbf     .L_not_aligned_and_len_larger_16bytes
+    ldw     r9, (sp, 0)
+    ldw     r10, (sp, 4)
+    addi    sp, 8
+    ldw     r8, (sp,12)
+
+.L_not_aligned_and_len_less_16bytes:
+    cmplti  r4, 4
+    jbf     .L2
+    rsubi   r6, 4                                   /* r6 is used to stored the misaligned bits */
+    subu    r3, r6                                 /* initial the position */
+    ldw     r11, (sp, 0)
+    ldw     r12, (sp, 4)
+    ldw     r13, (sp, 8)
+    addi    sp, 16
+    jbr     .L_copy_by_byte
+.L2:
+    ldw     r5, (r3, 0)
+    GET_FRONT_BITS r1 r12
+    mov     r11, r1
+    mov     r1, r5
+    GET_AFTER_BITS r5 r13
+    or      r5, r11
+    stw     r5, (r7, 0)
+    subi    r4, 4
+    addi    r3, 4
+    addi    r7, 4
+    jbr     .L_not_aligned_and_len_less_16bytes
+
+.size   Wmemcpy, .-Wmemcpy
+
+libc_hidden_def(Wmemcpy)
+.weak Wmemcpy
diff --git a/libc/string/csky/cskyv1/strcmp.S b/libc/string/csky/cskyv1/strcmp.S
new file mode 100644
index 0000000..e22f29e
--- /dev/null
+++ b/libc/string/csky/cskyv1/strcmp.S
@@ -0,0 +1,185 @@ 
+#include <features.h>
+#include <endian.h>
+
+#ifdef WANT_WIDE
+# define Wstrcmp wcscmp
+# define Wstrcoll wcscoll
+#else
+# define Wstrcmp strcmp
+# define Wstrcoll strcoll
+#endif
+
+/* FIXME attention!!! it may be a bug when WANT_WIDE define */
+/*libc_hidden_proto(Wstrcmp)*/
+	.align 2
+	.global Wstrcmp
+	.type   Wstrcmp, @function
+Wstrcmp:
+    mov        r6, r2
+
+    or         r2, r3
+    andi       r2, 0x3
+    cmpnei     r2, 0x0     /* d or s is aligned ?*/
+    bt         4f          /* if not aligned, goto 4f*/
+    1:                   /* if aligned, load word each time.*/
+    ldw        r2, (r6, 0)
+    ldw        r7, (r3, 0)
+    cmpne      r2, r7
+    bt         1f       /* if d[i] != s[i], goto 1f */
+    tstnbz     r2       /* if d[i] == s[i], check if d or s is at the end. */
+    bf         3f       /* if at the end, goto 3f (finish comparing) */
+
+    ldw        r2, (r6, 4)
+    ldw        r7, (r3, 4)
+    cmpne      r2, r7
+    bt         1f
+    tstnbz     r2
+    bf         3f
+
+    ldw        r2, (r6, 8)
+    ldw        r7, (r3, 8)
+    cmpne      r2, r7
+    bt         1f
+    tstnbz     r2
+    bf         3f
+
+    ldw        r2, (r6, 12)
+    ldw        r7, (r3, 12)
+    cmpne      r2, r7
+    bt         1f
+    tstnbz     r2
+    bf         3f
+
+    ldw        r2, (r6, 16)
+    ldw        r7, (r3, 16)
+    cmpne      r2, r7
+    bt         1f
+    tstnbz     r2
+    bf         3f
+
+    ldw        r2, (r6, 20)
+    ldw        r7, (r3, 20)
+    cmpne      r2, r7
+    bt         1f
+    tstnbz     r2
+    bf         3f
+
+    ldw        r2, (r6, 24)
+    ldw        r7, (r3, 24)
+    cmpne      r2, r7
+    bt         1f
+    tstnbz     r2
+    bf         3f
+
+    ldw        r2, (r6, 28)
+    ldw        r7, (r3, 28)
+    cmpne      r2, r7
+    bt         1f
+    tstnbz     r2
+    bf         3f
+
+    addi       r6, 32
+    addi       r3, 32
+    br         1b
+
+#ifdef __CSKYBE__
+    /* d[i] != s[i] in word, so we check byte 0 ? */
+    1:
+    xtrb0      r1, r2
+    mov        r4, r1
+    xtrb0      r1, r7
+    cmpne      r4, r1
+    bt         2f
+    cmpnei     r4, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb1      r1, r2
+    mov        r4, r1
+    xtrb1      r1, r7
+    cmpne      r4, r1
+    bt         2f
+    cmpnei     r4, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb2      r1, r2
+    mov        r4, r1
+    xtrb2      r1, r7
+    cmpne      r4, r1
+    bt         2f
+    cmpnei     r4, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb3      r1, r2
+    mov        r4, r1
+    xtrb3      r1, r7
+
+#else /* little endian */
+    /* d[i] != s[i] in word, so we check byte 0 ? */
+1:
+    xtrb3      r1, r2
+    mov        r4, r1
+    xtrb3      r1, r7
+    cmpne      r4, r1
+    bt         2f
+    cmpnei     r4, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb2      r1, r2
+    mov        r4, r1
+    xtrb2      r1, r7
+    cmpne      r4, r1
+    bt         2f
+    cmpnei     r4, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb1      r1, r2
+    mov        r4, r1
+    xtrb1      r1, r7
+    cmpne      r4, r1
+    bt         2f
+    cmpnei     r4, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb0      r1, r2
+    mov        r4, r1
+    xtrb0      r1, r7
+
+#endif
+    /* get the result when d[i] != s[i] */
+2:
+    subu       r4, r1
+    mov        r2, r4
+    jmp        r15
+
+    /* return when d[i] == s[i] */
+3:
+    subu       r2, r7
+    jmp        r15
+
+     /* cmp when d or s is not aligned */
+4:
+     ldb       r2, (r6,0)
+     ldb       r7, (r3, 0)
+     cmpne     r2, r7
+     bt        3b
+     addi      r3, 1
+     addi      r6, 1
+     cmpnei    r2, 0
+     bt        4b
+     jmp       r15
+
+     .size   Wstrcmp, .-Wstrcmp
+
+libc_hidden_def(Wstrcmp)
+.weak Wstrcmp
+#ifndef __UCLIBC_HAS_LOCALE__
+/* libc_hidden_proto(Wstrcoll) */
+strong_alias(Wstrcmp,Wstrcoll)
+libc_hidden_def(Wstrcoll)
+#endif
diff --git a/libc/string/csky/cskyv1/strcpy.S b/libc/string/csky/cskyv1/strcpy.S
new file mode 100644
index 0000000..c2f1e7a
--- /dev/null
+++ b/libc/string/csky/cskyv1/strcpy.S
@@ -0,0 +1,139 @@ 
+#include <features.h>
+#include <endian.h>
+
+#ifdef WANT_WIDE
+# define Wstrcpy wcscpy
+#else
+# define Wstrcpy strcpy
+#endif
+
+	.align 2
+	.global Wstrcpy
+	.type   Wstrcpy, @function
+Wstrcpy:
+
+		mov     r6, r2
+        mov     r7, r3
+        or      r7, r6
+        andi    r7, 3
+        cmpnei  r7, 0
+        bf      2f
+       1:
+        ldb     r5, (r3)
+        stb     r5, (r6)
+        addi    r3, 1
+        addi    r6, 1
+        cmpnei  r5, 0
+        bt      1b
+       1:
+        jmp     r15
+
+       2:
+        ldw     r5, (r3)
+        tstnbz  r5
+        bf      10f
+        stw     r5, (r6)
+
+        ldw     r5, (r3, 4)
+        tstnbz  r5
+        bf      3f
+        stw     r5, (r6, 4)
+
+        ldw     r5, (r3, 8)
+        tstnbz  r5
+        bf      4f
+        stw     r5, (r6, 8)
+
+        ldw     r5, (r3, 12)
+        tstnbz  r5
+        bf      5f
+        stw     r5, (r6, 12)
+
+        ldw     r5, (r3, 16)
+        tstnbz  r5
+        bf      6f
+        stw     r5, (r6, 16)
+
+        ldw     r5, (r3, 20)
+        tstnbz  r5
+        bf      7f
+        stw     r5, (r6, 20)
+
+        ldw     r5, (r3, 24)
+        tstnbz  r5
+        bf      8f
+        stw     r5, (r6, 24)
+
+        ldw     r5, (r3, 28)
+        tstnbz  r5
+        bf      9f
+        stw     r5, (r6, 28)
+
+        addi    r6, 32
+        addi    r3, 32
+        br      2b
+
+       3:
+        addi    r6, 4
+        br      10f
+
+       4:
+        addi    r6, 8
+        br      10f
+
+       5:
+        addi    r6, 12
+        br      10f
+
+       6:
+        addi    r6, 16
+        br      10f
+
+       7:
+        addi    r6, 20
+        br      10f
+
+       8:
+        addi    r6, 24
+        br      10f
+
+       9:
+        addi    r6, 28
+
+       10:
+#ifdef __CSKYBE__
+        xtrb0   r1, r5
+        stb     r1, (r6)
+        cmpnei  r1, 0
+        bf      5f
+        xtrb1   r1, r5
+        stb     r1, (r6, 1)
+        cmpnei  r1, 0
+        bf      5f
+        xtrb2   r1, r5
+        stb     r1, (r6, 2 )
+        cmpnei  r1, 0
+        bf      5f
+        stw     r5, (r6)
+
+#else
+        xtrb3   r1, r5
+        stb     r1, (r6)
+        cmpnei  r1, 0
+        bf      5f
+        xtrb2   r1, r5
+        stb     r1, (r6, 1)
+        cmpnei  r1, 0
+        bf      5f
+        xtrb1   r1, r5
+        stb     r1, (r6, 2)
+        cmpnei  r1, 0
+        bf      5f
+        stw     r5, (r6)
+#endif
+       5:
+        jmp     r15
+
+
+libc_hidden_def(Wstrcpy)
+.weak Wstrcpy
diff --git a/libc/string/csky/cskyv2/abiv2_memcpy.S b/libc/string/csky/cskyv2/abiv2_memcpy.S
new file mode 100644
index 0000000..c112ec0
--- /dev/null
+++ b/libc/string/csky/cskyv2/abiv2_memcpy.S
@@ -0,0 +1,184 @@ 
+.macro      GET_FRONT_BITS rx ry
+#ifdef      __cskyLE__
+    lsr     \rx, \ry
+#else
+    lsl     \rx, \ry
+#endif
+.endm
+
+.macro      GET_AFTER_BITS rx ry
+#ifdef      __cskyLE__
+    lsl     \rx, \ry
+#else
+    lsr     \rx, \ry
+#endif
+.endm
+
+
+#ifdef WANT_WIDE
+# define Wmemcpy wmemcpy
+#else
+# define Wmemcpy memcpy
+#endif
+
+/* void *memcpy(void *dest, const void *src, size_t n); */
+
+    .text
+	.align 2
+	.global Wmemcpy
+	.type   Wmemcpy, @function
+Wmemcpy:
+    mov     r3, r0
+    cmplti  r2, 4                                            /* If len less than 4 bytes */
+    jbt     .L_copy_by_byte
+
+    mov     r12, r0
+    andi    r12, 3
+    bnez    r12, .L_dest_not_aligned                         /* If dest is not 4 bytes aligned */
+.L0:
+    mov     r12, r1
+    andi    r12, 3
+    bnez    r12, .L_dest_aligned_but_src_not_aligned         /* If dest is aligned, but src is not aligned */
+
+    cmplti  r2, 16                                           /* dest and src are all aligned */
+    jbt     .L_aligned_and_len_less_16bytes                  /* If len less than 16 bytes */
+
+.L_aligned_and_len_larger_16bytes:                           /* src and dst are all aligned, and len > 16 bytes */
+    ldw     r18, (r1, 0)
+    ldw     r19, (r1, 4)
+    ldw     r20, (r1, 8)
+    ldw     r21, (r1, 12)
+    stw     r18, (r3, 0)
+    stw     r19, (r3, 4)
+    stw     r20, (r3, 8)
+    stw     r21, (r3, 12)
+    subi    r2, 16
+    addi    r1, 16
+    addi    r3, 16
+    cmplti  r2, 16
+    jbf     .L_aligned_and_len_larger_16bytes
+
+.L_aligned_and_len_less_16bytes:
+    cmplti  r2, 4
+    jbt     .L_copy_by_byte
+    ldw     r18, (r1, 0)
+    stw     r18, (r3, 0)
+    subi    r2, 4
+    addi    r1, 4
+    addi    r3, 4
+    jbr     .L_aligned_and_len_less_16bytes
+
+.L_copy_by_byte:                                    /* len less than 4 bytes */
+    cmpnei  r2, 0
+    jbf     .L_return
+    ldb     r18, (r1, 0)
+    stb     r18, (r3, 0)
+    subi    r2, 1
+    addi    r1, 1
+    addi    r3, 1
+    jbr     .L_copy_by_byte
+
+.L_return:
+    rts
+
+/* If dest is not aligned, just copying some bytes makes the dest align.
+   After that, we judge whether the src is aligned. */
+
+.L_dest_not_aligned:
+    rsub    r13, r1, r3                              /* consider overlapped case */
+    abs     r13, r13
+    cmplt   r13, r2
+    jbt     .L_copy_by_byte
+
+.L1:
+    ldb     r18, (r1, 0)                             /* makes the dest align. */
+    stb     r18, (r3, 0)
+    addi    r12, 1
+    subi    r2, 1
+    addi    r1, 1
+    addi    r3, 1
+    cmpnei  r12, 4
+    jbt     .L1
+    cmplti  r2, 4
+    jbt     .L_copy_by_byte
+    jbf     .L0                                     /* judge whether the src is aligned. */
+
+.L_dest_aligned_but_src_not_aligned:
+    rsub    r13, r1, r3                             /* consider overlapped case */
+    abs     r13, r13
+    cmplt   r13, r2
+    jbt     .L_copy_by_byte
+
+    bclri   r1, 0
+    bclri   r1, 1
+    ldw     r18, (r1, 0)
+    addi    r1, 4
+
+    movi    r13, 8
+    mult    r13, r12
+    mov     r24, r13                                /* r12 is used to store the misaligned bits */
+    rsubi   r13, 32
+    mov     r25, r13
+
+    cmplti  r2, 16
+    jbt     .L_not_aligned_and_len_less_16bytes
+
+.L_not_aligned_and_len_larger_16bytes:
+    ldw     r20, (r1, 0)
+    ldw     r21, (r1, 4)
+    ldw     r22, (r1, 8)
+    ldw     r23, (r1, 12)
+
+    GET_FRONT_BITS r18 r24                          /* little or big endian? */
+    mov     r19, r20
+    GET_AFTER_BITS r20 r25
+    or      r20, r18
+
+    GET_FRONT_BITS r19 r24
+    mov     r18, r21
+    GET_AFTER_BITS r21 r13
+    or      r21, r19
+
+    GET_FRONT_BITS r18 r24
+    mov     r19, r22
+    GET_AFTER_BITS r22 r25
+    or      r22, r18
+
+    GET_FRONT_BITS r19 r24
+    mov     r18, r23
+    GET_AFTER_BITS r23 r25
+    or      r23, r19
+
+    stw     r20, (r3, 0)
+    stw     r21, (r3, 4)
+    stw     r22, (r3, 8)
+    stw     r23, (r3, 12)
+    subi    r2, 16
+    addi    r1, 16
+    addi    r3, 16
+    cmplti  r2, 16
+    jbf     .L_not_aligned_and_len_larger_16bytes
+
+.L_not_aligned_and_len_less_16bytes:
+    cmplti  r2, 4
+    jbf     .L2
+    rsubi   r12, 4                                   /* r12 is used to stored the misaligned bits */
+    subu    r1, r12                                  /* initial the position */
+    jbr     .L_copy_by_byte
+.L2:
+    ldw     r21, (r1, 0)
+    GET_FRONT_BITS r18 r24
+    mov     r19, r18
+    mov     r18, r21
+    GET_AFTER_BITS r21 r25
+    or      r21, r19
+    stw     r21, (r3, 0)
+    subi    r2, 4
+    addi    r1, 4
+    addi    r3, 4
+    jbr     .L_not_aligned_and_len_less_16bytes
+
+.size   Wmemcpy, .-Wmemcpy
+
+libc_hidden_def(Wmemcpy)
+.weak Wmemcpy
diff --git a/libc/string/csky/cskyv2/abiv2_strcmp.S b/libc/string/csky/cskyv2/abiv2_strcmp.S
new file mode 100644
index 0000000..202da7c
--- /dev/null
+++ b/libc/string/csky/cskyv2/abiv2_strcmp.S
@@ -0,0 +1,168 @@ 
+#include <endian.h>
+#include "macro.S"
+
+#ifdef WANT_WIDE
+# define Wstrcmp wcscmp
+# define Wstrcoll wcscoll
+#else
+# define Wstrcmp strcmp
+# define Wstrcoll strcoll
+#endif
+
+/* FIXME attention!!! it may be a bug when WANT_WIDE define */
+/*libc_hidden_proto(Wstrcmp)*/
+	.align 2
+	.global Wstrcmp
+	.type   Wstrcmp, @function
+Wstrcmp:
+    mov        a3, a0
+
+    or         a0, a1
+    andi       a0, 0x3
+    M_BNEZ     a0, 4f
+    1:                   // if aligned, load word each time.
+
+    ldw        a0, (a3, 0)
+    ldw        t0, (a1, 0)
+    M_BNE      a0, t0, 1f // if d[i] != s[i], goto 1f
+    tstnbz     a0       // if d[i] == s[i], check if d or s is at the end.
+    bf         3f       // if at the end, goto 3f (finish comparing)
+    ldw        a0, (a3, 4)
+    ldw        t0, (a1, 4)
+    M_BNE      a0, t0, 1f
+    tstnbz     a0
+    bf         3f
+
+    ldw        a0, (a3, 8)
+    ldw        t0, (a1, 8)
+    M_BNE      a0, t0, 1f
+    tstnbz     a0
+    bf         3f
+
+    ldw        a0, (a3, 12)
+    ldw        t0, (a1, 12)
+    M_BNE      a0, t0, 1f
+    tstnbz     a0
+    bf         3f
+
+    ldw        a0, (a3, 16)
+    ldw        t0, (a1, 16)
+    M_BNE      a0, t0, 1f
+    tstnbz     a0
+    bf         3f
+
+    ldw        a0, (a3, 20)
+    ldw        t0, (a1, 20)
+    M_BNE      a0, t0, 1f
+    tstnbz     a0
+    bf         3f
+
+    ldw        a0, (a3, 24)
+    ldw        t0, (a1, 24)
+    M_BNE      a0, t0, 1f
+    tstnbz     a0
+    bf         3f
+
+    ldw        a0, (a3, 28)
+    ldw        t0, (a1, 28)
+    M_BNE      a0, t0, 1f
+    tstnbz     a0
+    bf         3f
+
+    addi       a3, 32
+    addi       a1, 32
+    br         1b
+
+#ifdef __CSKYBE__
+    /* d[i] != s[i] in word, so we check byte 0 ? */
+    1:
+    xtrb0      t1, a0
+    mov        a2, t1
+    xtrb0      t1, t0
+    M_BNE      a2, t1, 2f
+    cmpnei     a2, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb1      t1, a0
+    mov        a2, t1
+    xtrb1      t1, t0
+    M_BNE      a2, t1, 2f
+    cmpnei     a2, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb2      t1, a0
+    mov        a2, t1
+    xtrb2      t1, t0
+    M_BNE      a2, t1, 2f
+    cmpnei     a2, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb3      t1, a0
+    mov        a2, t1
+    xtrb3      t1, t0
+
+#else /* little endian */
+    /* d[i] != s[i] in word, so we check byte 0 ? */
+    1:
+    xtrb3      t1, a0
+    mov        a2, t1
+    xtrb3      t1, t0
+    M_BNE      a2, t1, 2f
+    cmpnei     a2, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb2      t1, a0
+    mov        a2, t1
+    xtrb2      t1, t0
+    M_BNE      a2, t1, 2f
+    cmpnei     a2, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb1      t1, a0
+    mov        a2, t1
+    xtrb1      t1, t0
+    M_BNE      a2, t1, 2f
+    cmpnei     a2, 0
+    bf         2f
+
+    /* d[i] != s[i] in word, so we check byte 1 ? */
+    xtrb0      t1, a0
+    mov        a2, t1
+    xtrb0      t1, t0
+
+#endif
+    /* get the result when d[i] != s[i] */
+    2:
+    subu       a2, t1
+    mov        a0, a2
+    jmp        r15
+
+    /* return when d[i] == s[i] */
+    3:
+    subu       a0, t0
+    jmp        r15
+
+     /* cmp when d or s is not aligned */
+    4:
+    ldb       a0, (a3,0)
+    ldb       t0, (a1, 0)
+    M_BNE     a0, t0, 3b
+    addi      a1, 1
+    addi      a3, 1
+    M_BNEZ    a0, 4b
+    jmp        r15
+
+    .size   Wstrcmp, .-Wstrcmp
+
+libc_hidden_def(Wstrcmp)
+.weak Wstrcmp
+#ifndef __UCLIBC_HAS_LOCALE__
+/* libc_hidden_proto(Wstrcoll) */
+strong_alias(Wstrcmp,Wstrcoll)
+libc_hidden_def(Wstrcoll)
+#endif
diff --git a/libc/string/csky/cskyv2/abiv2_strcpy.S b/libc/string/csky/cskyv2/abiv2_strcpy.S
new file mode 100644
index 0000000..20262fe
--- /dev/null
+++ b/libc/string/csky/cskyv2/abiv2_strcpy.S
@@ -0,0 +1,129 @@ 
+#include <endian.h>
+#include "macro.S"
+
+#ifdef WANT_WIDE
+# define Wstrcpy wcscpy
+#else
+# define Wstrcpy strcpy
+#endif
+
+	.align 2
+	.global Wstrcpy
+	.type   Wstrcpy, @function
+Wstrcpy:
+
+        mov     a3, a0
+        or      a2, a1, a3
+        andi    t0, a2, 3
+        M_BEZ   t0, 2f
+        mov     t0, a1
+       1:
+        ld.b    a2, (t0)
+        stb     a2, (a3)
+        addi    t0, t0, 1
+        addi    a3, a3, 1
+        M_BNEZ  a2, 1b
+
+        jmp     r15
+
+       2:
+        ldw     a2, (a1)
+        tstnbz  a2
+        bf      11f
+        stw     a2, (a3)
+
+        ldw     a2, (a1, 4)
+        tstnbz  a2
+        bf      4f
+        stw     a2, (a3, 4)
+
+        ldw     a2, (a1, 8)
+        tstnbz  a2
+        bf      5f
+        stw     a2, (a3, 8)
+
+        ldw     a2, (a1, 12)
+        tstnbz  a2
+        bf      6f
+        stw     a2, (a3, 12)
+
+        ldw     a2, (a1, 16)
+        tstnbz  a2
+        bf      7f
+        stw     a2, (a3, 16)
+
+        ldw     a2, (a1, 20)
+        tstnbz  a2
+        bf      8f
+        stw     a2, (a3, 20)
+
+        ldw     a2, (a1, 24)
+        tstnbz  a2
+        bf      9f
+        stw     a2, (a3, 24)
+
+        ldw     a2, (a1, 28)
+        tstnbz  a2
+        bf      10f
+        stw     a2, (a3, 28)
+
+        addi     a3, 32
+        addi     a1, 32
+        br       2b
+
+       4:
+        addi    a3, 4
+        br      11f
+
+       5:
+        addi    a3, 8
+        br      11f
+
+       6:
+        addi    a3, 12
+        br      11f
+
+       7:
+        addi    a3, 16
+        br      11f
+
+       8:
+        addi    a3, 20
+        br      11f
+
+       9:
+        addi    a3, 24
+        br      11f
+
+       10:
+        addi    a3, 28
+       11:
+#ifdef __CSKYBE__
+        xtrb0   t0, a2
+        st.b    t0, (a3)
+        M_BEZ   t0, 5f
+        xtrb1   t0, a2
+        st.b    t0, (a3, 1)
+        M_BEZ   t0, 5f
+        xtrb2   t0, a2
+        st.b    t0, (a3, 2 )
+        M_BEZ   t0, 5f
+        stw     a2, (a3)
+#else
+        xtrb3   t0, a2
+        st.b    t0, (a3)
+        M_BEZ   t0, 5f
+        xtrb2   t0, a2
+        st.b    t0, (a3, 1)
+        M_BEZ   t0, 5f
+        xtrb1   t0, a2
+        st.b    t0, (a3, 2)
+        M_BEZ   t0, 5f
+        stw     a2, (a3)
+#endif
+       5:
+	jmp     r15
+
+
+libc_hidden_def(Wstrcpy)
+.weak Wstrcpy
diff --git a/libc/string/csky/cskyv2/macro.S b/libc/string/csky/cskyv2/macro.S
new file mode 100644
index 0000000..047645c
--- /dev/null
+++ b/libc/string/csky/cskyv2/macro.S
@@ -0,0 +1,13 @@ 
+.macro M_BEZ rx, label
+	bez   \rx, \label
+.endm
+
+.macro M_BNEZ rx, label
+	bnez  \rx, \label
+.endm
+
+.macro M_BNE rx, ry, label
+	cmpne \rx, \ry
+	bt    \label
+.endm
+
diff --git a/libc/string/csky/memcpy.S b/libc/string/csky/memcpy.S
new file mode 100644
index 0000000..51d258a
--- /dev/null
+++ b/libc/string/csky/memcpy.S
@@ -0,0 +1,7 @@ 
+#include <features.h>
+
+#ifdef __CSKYABIV2__
+#include "cskyv2/abiv2_memcpy.S"
+#else
+#include "cskyv1/memcpy.S"
+#endif
diff --git a/libc/string/csky/strcmp.S b/libc/string/csky/strcmp.S
new file mode 100644
index 0000000..05a88c9
--- /dev/null
+++ b/libc/string/csky/strcmp.S
@@ -0,0 +1,7 @@ 
+#include <features.h>
+
+#ifdef __CSKYABIV2__
+#include "cskyv2/abiv2_strcmp.S"
+#else
+#include "cskyv1/strcmp.S"
+#endif
diff --git a/libc/string/csky/strcpy.S b/libc/string/csky/strcpy.S
new file mode 100644
index 0000000..dd3be04
--- /dev/null
+++ b/libc/string/csky/strcpy.S
@@ -0,0 +1,7 @@ 
+#include <features.h>
+
+#ifdef __CSKYABIV2__
+#include "cskyv2/abiv2_strcpy.S"
+#else
+#include "cskyv1/strcpy.S"
+#endif
diff --git a/libc/sysdeps/linux/common/posix_fadvise.c b/libc/sysdeps/linux/common/posix_fadvise.c
index f4ec4f8..d2fb57e 100644
--- a/libc/sysdeps/linux/common/posix_fadvise.c
+++ b/libc/sysdeps/linux/common/posix_fadvise.c
@@ -40,7 +40,7 @@  int posix_fadvise(int fd, off_t offset, off_t len, int advice)
 #  if __WORDSIZE == 64
 	ret = INTERNAL_SYSCALL(fadvise64_64, err, 4, fd, offset, len, advice);
 #  else
-#   if defined (__arm__) || defined (__nds32__) || \
+#   if defined (__arm__) || defined (__nds32__) || defined(__csky__) || \
       (defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) && (defined(__powerpc__) || defined(__xtensa__)))
 	/* arch with 64-bit data in even reg alignment #1: [powerpc/xtensa]
 	 * custom syscall handler (rearranges @advice to avoid register hole punch) */
diff --git a/libc/sysdeps/linux/common/posix_fadvise64.c b/libc/sysdeps/linux/common/posix_fadvise64.c
index 2d4e466..a7ce1ce 100644
--- a/libc/sysdeps/linux/common/posix_fadvise64.c
+++ b/libc/sysdeps/linux/common/posix_fadvise64.c
@@ -24,7 +24,7 @@  int posix_fadvise64(int fd, off64_t offset, off64_t len, int advice)
 	int ret;
 	INTERNAL_SYSCALL_DECL (err);
 	/* ARM has always been funky. */
-#if defined (__arm__) || defined (__nds32__) || \
+#if defined (__arm__) || defined (__nds32__) || defined (__csky__) || \
     (defined(__UCLIBC_SYSCALL_ALIGN_64BIT__) && (defined(__powerpc__) || defined(__xtensa__)))
 	/* arch with 64-bit data in even reg alignment #1: [powerpc/xtensa]
 	 * custom syscall handler (rearranges @advice to avoid register hole punch) */
diff --git a/libc/sysdeps/linux/csky/Makefile b/libc/sysdeps/linux/csky/Makefile
new file mode 100644
index 0000000..43dc60a
--- /dev/null
+++ b/libc/sysdeps/linux/csky/Makefile
@@ -0,0 +1,6 @@ 
+top_srcdir=../../../../
+top_builddir=../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules
diff --git a/libc/sysdeps/linux/csky/Makefile.arch b/libc/sysdeps/linux/csky/Makefile.arch
new file mode 100644
index 0000000..704b36a
--- /dev/null
+++ b/libc/sysdeps/linux/csky/Makefile.arch
@@ -0,0 +1,6 @@ 
+CSRC-y := clone.c __syscall_error.c cacheflush.c
+
+SSRC-y := __longjmp.S setjmp.S
+SSRC-y += libc-read_tp.S vfork.S csky_clone.S
+
+
diff --git a/libc/sysdeps/linux/csky/__longjmp.S b/libc/sysdeps/linux/csky/__longjmp.S
new file mode 100644
index 0000000..66ad626
--- /dev/null
+++ b/libc/sysdeps/linux/csky/__longjmp.S
@@ -0,0 +1,39 @@ 
+#include <sysdep.h>
+
+ENTRY(__longjmp)
+        ldw	sp, (a0, 0)
+	ldw	lr, (a0, 4)
+
+	ldw	l0, (a0, 8)
+	ldw	l1, (a0, 12)
+	ldw	l2, (a0, 16)
+	ldw	l3, (a0, 20)
+	ldw	l4, (a0, 24)
+	ldw	l5, (a0, 28)
+
+#ifdef __CSKYABIV2__
+	ldw	l6, (a0, 32)
+	ldw	l7, (a0, 36)
+	ldw	l8, (a0, 40)
+	ldw	l9, (a0, 44)
+
+	ldw	r26, (a0, 48)
+	ldw	r27, (a0, 52)
+	ldw	gb,  (a0, 56)
+	ldw	r29, (a0, 60)
+	ldw	r30, (a0, 64)
+	ldw	tls, (a0, 68)
+#else
+	ldw	gb, (a0, 32)
+#endif
+
+	mov    a0, a1
+	cmpnei a1, 0
+	bt     1f
+	movi   a0, 1
+1:
+	rts
+
+END(__longjmp)
+libc_hidden_def(__longjmp)
+
diff --git a/libc/sysdeps/linux/csky/__syscall_error.c b/libc/sysdeps/linux/csky/__syscall_error.c
new file mode 100644
index 0000000..346ce8a
--- /dev/null
+++ b/libc/sysdeps/linux/csky/__syscall_error.c
@@ -0,0 +1,9 @@ 
+#include <errno.h>
+#include <features.h>
+
+int __syscall_error(int err_no)
+{
+	__set_errno(-err_no);
+	return -1;
+}
+
diff --git a/libc/sysdeps/linux/csky/bits/atomic.h b/libc/sysdeps/linux/csky/bits/atomic.h
new file mode 100644
index 0000000..231d58f
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/atomic.h
@@ -0,0 +1,93 @@ 
+#ifndef __CSKY_ATOMIC_H_
+#define __CSKY_ATOMIC_H_
+
+#include <stdint.h>
+#include <sysdep.h>
+
+typedef int8_t atomic8_t;
+typedef uint8_t uatomic8_t;
+typedef int_fast8_t atomic_fast8_t;
+typedef uint_fast8_t uatomic_fast8_t;
+
+typedef int16_t atomic16_t;
+typedef uint16_t uatomic16_t;
+typedef int_fast16_t atomic_fast16_t;
+typedef uint_fast16_t uatomic_fast16_t;
+
+typedef int32_t atomic32_t;
+typedef uint32_t uatomic32_t;
+typedef int_fast32_t atomic_fast32_t;
+typedef uint_fast32_t uatomic_fast32_t;
+
+typedef int64_t atomic64_t;
+typedef uint64_t uatomic64_t;
+typedef int_fast64_t atomic_fast64_t;
+typedef uint_fast64_t uatomic_fast64_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+# define __arch_compare_and_exchange_bool_8_int(mem, newval, oldval) \
+  (abort (), 0)
+
+# define __arch_compare_and_exchange_bool_16_int(mem, newval, oldval) \
+  (abort (), 0)
+
+# define __arch_compare_and_exchange_bool_32_int(mem, newval, oldval) \
+  ({ __typeof(mem) _mem = (mem);                       \
+    __typeof(oldval) _oldval = oldval;                 \
+    __typeof(newval) _newval = newval;                 \
+    register __typeof(oldval) _a0 __asm__ ("a0") = _oldval;        \
+    register __typeof(newval) _a1 __asm__ ("a1") = _newval;        \
+    register __typeof(mem) _a2 __asm__ ("a2") = _mem;          \
+    __asm__ __volatile__ ("trap   2;"                     \
+     : "+r" (_a0) : "r" (_a1) , "r" (_a2)                 \
+     : "a3", "memory");                \
+    _a0; })
+
+#  define __arch_compare_and_exchange_bool_64_int(mem, newval, oldval) \
+  (abort (), 0)
+
+#define __arch_compare_and_exchange_val_8_int(mem, newval, oldval) \
+	(abort (), 0)
+
+#define __arch_compare_and_exchange_val_16_int(mem, newval, oldval) \
+	(abort (), 0)
+
+#define __arch_compare_and_exchange_val_32_int(mem, newval, oldval) \
+  ({ __typeof (mem) _mem = (mem);                       \
+	__typeof (*mem) __gret = *_mem;                     \
+    unsigned int _tmp = 0;                                  \
+    __typeof (oldval) _oldval = oldval;                 \
+    __typeof (newval) _newval = newval;                 \
+    register __typeof (oldval) _a0 __asm__ ("a0") = _oldval;    \
+    register __typeof (newval) _a1 __asm__ ("a1") = _newval;    \
+    register __typeof (mem) _a2 __asm__ ("a2") = _mem;          \
+        __asm__ __volatile__ ("1:\n\t"        \
+      "ldw      %1, (%4, 0x0)\n\t"            \
+      "cmpne    %1, %0\n\t"                   \
+      "bt       2f\n\t"                       \
+      "mov      %2, %0\n\t"                   \
+      "trap     2\n\t"                        \
+      "cmpnei   %0, 0\n\t"                    \
+      "mov      %0, %2\n\t"                   \
+      "bt       1b\n\t"                       \
+      "2:         \n\t"                       \
+     :"+r" (_a0), "+r"(__gret), "+r" (_tmp) :"r" (_a1) , "r" (_a2)    \
+     : "a3", "memory");                \
+    __gret; })
+
+# define __arch_compare_and_exchange_val_64_int(mem, newval, oldval) \
+	(abort (), 0)
+
+# define atomic_compare_and_exchange_bool_acq(mem, new, old)    \
+  __atomic_bool_bysize (__arch_compare_and_exchange_bool, int,  \
+            mem, new, old)
+
+# define atomic_compare_and_exchange_val_acq(mem, new, old) \
+  __atomic_val_bysize (__arch_compare_and_exchange_val, int,    \
+               mem, new, old)
+
+#endif
diff --git a/libc/sysdeps/linux/csky/bits/endian.h b/libc/sysdeps/linux/csky/bits/endian.h
new file mode 100644
index 0000000..09af89c
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/endian.h
@@ -0,0 +1,10 @@ 
+#ifndef _ENDIAN_H
+# error "Never use <bits/endian.h> directly; include <endian.h> instead."
+#endif
+
+/* CSKY CPU can be either big or little endian.  */
+#ifdef __cskyBE__
+# define __BYTE_ORDER __BIG_ENDIAN
+#else
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
diff --git a/libc/sysdeps/linux/csky/bits/fcntl.h b/libc/sysdeps/linux/csky/bits/fcntl.h
new file mode 100644
index 0000000..feacdad
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/fcntl.h
@@ -0,0 +1,193 @@ 
+#ifndef	_FCNTL_H
+# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
+#endif
+
+
+#include <sys/types.h>
+#ifdef __USE_GNU
+# include <bits/uio.h>
+#endif
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE	   0003
+#define O_RDONLY	     00
+#define O_WRONLY	     01
+#define O_RDWR		     02
+#define O_CREAT		   0100	/* not fcntl */
+#define O_EXCL		   0200	/* not fcntl */
+#define O_NOCTTY	   0400	/* not fcntl */
+#define O_TRUNC		  01000	/* not fcntl */
+#define O_APPEND	  02000
+#define O_NONBLOCK	  04000
+#define O_NDELAY	O_NONBLOCK
+#define O_SYNC		 010000
+#define O_FSYNC		 O_SYNC
+#define O_ASYNC		 020000
+
+#ifdef __USE_GNU
+# define O_DIRECTORY	 040000	/* Must be a directory.	 */
+# define O_NOFOLLOW	0100000	/* Do not follow links.	 */
+# define O_DIRECT	0200000	/* Direct disk access.	*/
+# define O_STREAMING	04000000/* streaming access */
+# define O_CLOEXEC	02000000 /* set close_on_exec */
+#endif
+
+/* For now Linux has synchronisity options for data and read operations.
+   We define the symbols here but let them do the same as O_SYNC since
+   this is a superset.	*/
+#if defined __USE_POSIX199309 || defined __USE_UNIX98
+# define O_DSYNC	O_SYNC	/* Synchronize data.  */
+# define O_RSYNC	O_SYNC	/* Synchronize read operations.	 */
+#endif
+
+#ifdef __USE_LARGEFILE64
+# define O_LARGEFILE	0400000
+#endif
+
+/* Values for the second argument to `fcntl'.  */
+#define F_DUPFD		0	/* Duplicate file descriptor.  */
+#define F_GETFD		1	/* Get file descriptor flags.  */
+#define F_SETFD		2	/* Set file descriptor flags.  */
+#define F_GETFL		3	/* Get file status flags.  */
+#define F_SETFL		4	/* Set file status flags.  */
+#ifndef __USE_FILE_OFFSET64
+# define F_GETLK	5	/* Get record locking info.  */
+# define F_SETLK	6	/* Set record locking info (non-blocking).  */
+# define F_SETLKW	7	/* Set record locking info (blocking).	*/
+#else
+# define F_GETLK	F_GETLK64  /* Get record locking info.	*/
+# define F_SETLK	F_SETLK64  /* Set record locking info (non-blocking).*/
+# define F_SETLKW	F_SETLKW64 /* Set record locking info (blocking).  */
+#endif
+#define F_GETLK64	12	/* Get record locking info.  */
+#define F_SETLK64	13	/* Set record locking info (non-blocking).  */
+#define F_SETLKW64	14	/* Set record locking info (blocking).	*/
+
+#if defined __USE_BSD || defined __USE_XOPEN2K
+# define F_SETOWN	8	/* Get owner of socket (receiver of SIGIO).  */
+# define F_GETOWN	9	/* Set owner of socket (receiver of SIGIO).  */
+#endif
+
+#ifdef __USE_GNU
+# define F_SETSIG	10	/* Set number of signal to be sent.  */
+# define F_GETSIG	11	/* Get number of signal to be sent.  */
+#endif
+
+#ifdef __USE_GNU
+# define F_SETLEASE	1024	/* Set a lease.	 */
+# define F_GETLEASE	1025	/* Enquire what lease is active.  */
+# define F_NOTIFY	1026	/* Request notfications on a directory.	 */
+#endif
+
+/* For F_[GET|SET]FL.  */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* For posix fcntl() and `l_type' field of a `struct flock' for lockf().  */
+#define F_RDLCK		0	/* Read lock.  */
+#define F_WRLCK		1	/* Write lock.	*/
+#define F_UNLCK		2	/* Remove lock.	 */
+
+/* For old implementation of bsd flock().  */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+#ifdef __USE_BSD
+/* Operations for bsd flock(), also used by the kernel implementation.	*/
+# define LOCK_SH	1	/* shared lock */
+# define LOCK_EX	2	/* exclusive lock */
+# define LOCK_NB	4	/* or'd with one of the above to prevent
+				   blocking */
+# define LOCK_UN	8	/* remove lock */
+#endif
+
+#ifdef __USE_GNU
+# define LOCK_MAND	32	/* This is a mandatory flock:	*/
+# define LOCK_READ	64	/* ... which allows concurrent read operations.	 */
+# define LOCK_WRITE	128	/* ... which allows concurrent write operations.  */
+# define LOCK_RW	192	/* ... Which allows concurrent read & write operations.	 */
+#endif
+
+#ifdef __USE_GNU
+/* Types of directory notifications that may be requested with F_NOTIFY.  */
+# define DN_ACCESS	0x00000001	/* File accessed.  */
+# define DN_MODIFY	0x00000002	/* File modified.  */
+# define DN_CREATE	0x00000004	/* File created.  */
+# define DN_DELETE	0x00000008	/* File removed.  */
+# define DN_RENAME	0x00000010	/* File renamed.  */
+# define DN_ATTRIB	0x00000020	/* File changed attibutes.  */
+# define DN_MULTISHOT	0x80000000	/* Don't remove notifier.  */
+#endif
+
+struct flock
+  {
+    short int l_type;	/* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.	*/
+    short int l_whence;	/* Where `l_start' is relative to (like `lseek').  */
+#ifndef __USE_FILE_OFFSET64
+    __off_t l_start;	/* Offset where the lock begins.  */
+    __off_t l_len;	/* Size of the locked area; zero means until EOF.  */
+#else
+    __off64_t l_start;	/* Offset where the lock begins.  */
+    __off64_t l_len;	/* Size of the locked area; zero means until EOF.  */
+#endif
+    __pid_t l_pid;	/* Process holding the lock.  */
+  };
+
+#ifdef __USE_LARGEFILE64
+struct flock64
+  {
+    short int l_type;	/* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.	*/
+    short int l_whence;	/* Where `l_start' is relative to (like `lseek').  */
+    __off64_t l_start;	/* Offset where the lock begins.  */
+    __off64_t l_len;	/* Size of the locked area; zero means until EOF.  */
+    __pid_t l_pid;	/* Process holding the lock.  */
+  };
+#endif
+
+/* Define some more compatibility macros to be backward compatible with
+   BSD systems which did not managed to hide these kernel macros.  */
+#ifdef	__USE_BSD
+# define FAPPEND	O_APPEND
+# define FFSYNC		O_FSYNC
+# define FASYNC		O_ASYNC
+# define FNONBLOCK	O_NONBLOCK
+# define FNDELAY	O_NDELAY
+#endif /* Use BSD.  */
+
+/* Advise to `posix_fadvise'.  */
+#ifdef __USE_XOPEN2K
+# define POSIX_FADV_NORMAL	0 /* No further special treatment.  */
+# define POSIX_FADV_RANDOM	1 /* Expect random page references.  */
+# define POSIX_FADV_SEQUENTIAL	2 /* Expect sequential page references.	 */
+# define POSIX_FADV_WILLNEED	3 /* Will need these pages.  */
+# define POSIX_FADV_DONTNEED	4 /* Don't need these pages.  */
+# define POSIX_FADV_NOREUSE	5 /* Data will be accessed once.  */
+#endif
+
+__BEGIN_DECLS
+
+#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__
+
+/* Provide kernel hint to read ahead.  */
+extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count)
+    __THROW;
+
+
+/* Selective file content synch'ing.  */
+extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to,
+                            unsigned int __flags);
+
+/* Splice address range into a pipe.  */
+extern ssize_t vmsplice (int __fdout, const struct iovec *__iov,
+                         size_t __count, unsigned int __flags);
+
+/* Splice two files together.  */
+extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout,
+                       __off64_t *__offout, size_t __len,
+                       unsigned int __flags);
+
+/* In-kernel implementation of tee for pipe buffers.  */
+extern ssize_t tee (int __fdin, int __fdout, size_t __len,
+                    unsigned int __flags);
+
+#endif
+__END_DECLS
diff --git a/libc/sysdeps/linux/csky/bits/fenv.h b/libc/sysdeps/linux/csky/bits/fenv.h
new file mode 100644
index 0000000..606fe79
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/fenv.h
@@ -0,0 +1,58 @@ 
+#ifndef _FENV_H
+# error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
+#endif
+
+/* Define bits representing the exception.  We use the bit positions of
+   the appropriate bits in the FPSR Accrued Exception Byte.  */
+enum
+  {
+    FE_INEXACT = 1 << 3,
+#define FE_INEXACT	FE_INEXACT
+    FE_DIVBYZERO = 1 << 4,
+#define FE_DIVBYZERO	FE_DIVBYZERO
+    FE_UNDERFLOW = 1 << 5,
+#define FE_UNDERFLOW	FE_UNDERFLOW
+    FE_OVERFLOW = 1 << 6,
+#define FE_OVERFLOW	FE_OVERFLOW
+    FE_INVALID = 1 << 7
+#define FE_INVALID	FE_INVALID
+  };
+
+#define FE_ALL_EXCEPT \
+	(FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
+
+/* The csky FPU supports all of the four defined rounding modes.  We use
+   the bit positions in the FPCR Mode Control Byte as the values for the
+   appropriate macros.  */
+enum
+  {
+    FE_TONEAREST = 0,
+#define FE_TONEAREST	FE_TONEAREST
+    FE_TOWARDZERO = 1 << 4,
+#define FE_TOWARDZERO	FE_TOWARDZERO
+    FE_DOWNWARD = 2 << 4,
+#define FE_DOWNWARD	FE_DOWNWARD
+    FE_UPWARD = 3 << 4
+#define FE_UPWARD	FE_UPWARD
+  };
+
+/* Type representing exception flags.  */
+typedef unsigned int fexcept_t;
+
+/* Type representing floating-point environment.  This structure
+   corresponds to the layout of the block written by `fmovem'.  */
+typedef struct
+  {
+    unsigned int __control_register;
+    unsigned int __status_register;
+    unsigned int __instruction_address;
+  }
+fenv_t;
+
+/* If the default argument is used we use this value.  */
+#define FE_DFL_ENV	((__const fenv_t *) -1)
+
+#ifdef __USE_GNU
+/* Floating-point environment where none of the exceptions are masked.  */
+# define FE_NOMASK_ENV	((__const fenv_t *) -2)
+#endif
diff --git a/libc/sysdeps/linux/csky/bits/kernel_stat.h b/libc/sysdeps/linux/csky/bits/kernel_stat.h
new file mode 100644
index 0000000..079a01a
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/kernel_stat.h
@@ -0,0 +1,60 @@ 
+#ifndef _BITS_STAT_STRUCT_H
+#define _BITS_STAT_STRUCT_H
+
+#define STAT_HAVE_NSEC 1
+
+struct kernel_stat {
+#if defined(__cskyBE__)
+	unsigned short st_dev;
+	unsigned short __pad1;
+#else
+	unsigned long  st_dev;
+#endif
+	unsigned long  st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+#if defined(__cskyBE__)
+	unsigned short st_rdev;
+	unsigned short __pad2;
+#else
+	unsigned long  st_rdev;
+#endif
+	unsigned long  st_size;
+	unsigned long  st_blksize;
+	unsigned long  st_blocks;
+	struct timespec st_atim;
+	struct timespec st_mtim;
+	struct timespec st_ctim;
+	unsigned long  __unused4;
+	unsigned long  __unused5;
+};
+
+struct kernel_stat64 {
+	unsigned long long  st_dev;
+	unsigned char   __pad0[4];
+
+#define STAT64_HAS_BROKEN_ST_INO    1
+	unsigned long   __st_ino;
+	unsigned int    st_mode;
+	unsigned int    st_nlink;
+
+	unsigned long   st_uid;
+	unsigned long   st_gid;
+
+	unsigned long long  st_rdev;
+	unsigned char   __pad3[4];
+
+	long long       st_size;
+	unsigned long   st_blksize;
+	unsigned long long  st_blocks;  /* Number 512-byte blocks allocated. */
+
+	struct timespec st_atim;
+	struct timespec st_mtim;
+	struct timespec st_ctim;
+	unsigned long long  st_ino;
+};
+
+#endif	/*  _BITS_STAT_STRUCT_H */
+
diff --git a/libc/sysdeps/linux/csky/bits/kernel_types.h b/libc/sysdeps/linux/csky/bits/kernel_types.h
new file mode 100644
index 0000000..80c9d59
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/kernel_types.h
@@ -0,0 +1,47 @@ 
+/* Note that we use the exact same include guard #define names
+ * as asm/posix_types.h.  This will avoid gratuitous conflicts
+ * with the posix_types.h kernel header, and will ensure that
+ * our private content, and not the kernel header, will win.
+ *  -Erik
+ */
+#if !defined(__ARCH_CSKY_POSIX_TYPES_H) || !defined(__ASM_GENERIC_POSIX_TYPES_H)
+#define __ARCH_CSKY_POSIX_TYPES_H
+#define __ASM_GENERIC_POSIX_TYPES_H
+
+typedef unsigned short	__kernel_dev_t;
+typedef unsigned long	__kernel_ino_t;
+typedef unsigned short	__kernel_mode_t;
+typedef unsigned short	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef int		__kernel_pid_t;
+typedef unsigned short	__kernel_ipc_pid_t;
+typedef unsigned short	__kernel_uid_t;
+typedef unsigned short	__kernel_gid_t;
+typedef unsigned int	__kernel_size_t;
+typedef int		__kernel_ssize_t;
+typedef int		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+typedef unsigned int	__kernel_uid32_t;
+typedef unsigned int	__kernel_gid32_t;
+typedef unsigned short	__kernel_old_uid_t;
+typedef unsigned short	__kernel_old_gid_t;
+typedef long long	__kernel_loff_t;
+typedef __kernel_dev_t  __kernel_old_dev_t;
+typedef long		__kernel_long_t;
+typedef unsigned long	__kernel_ulong_t;
+
+typedef struct {
+#ifdef __USE_ALL
+	int val[2];
+#else
+	int __val[2];
+#endif
+} __kernel_fsid_t;
+
+#endif /* __ARCH_CSKY_POSIX_TYPES_H */
diff --git a/libc/sysdeps/linux/csky/bits/mathinline.h b/libc/sysdeps/linux/csky/bits/mathinline.h
new file mode 100644
index 0000000..d6ab1a2
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/mathinline.h
@@ -0,0 +1,445 @@ 
+#ifdef	__GNUC__
+
+#ifdef __USE_ISOC99
+
+/* ISO C99 defines some macros to perform unordered comparisons.  The
+   csky FPU supports this with special opcodes and we should use them.
+   These must not be inline functions since we have to be able to handle
+   all floating-point types.  */
+# define isgreater(x, y)					\
+   __extension__					\
+   ({ char __result;					\
+      __asm__ ("fcmp%.x %2,%1; fsogt %0"		\
+	       : "=dm" (__result) : "f" (x), "f" (y));	\
+      __result != 0; })
+
+# define isgreaterequal(x, y)				\
+   __extension__					\
+   ({ char __result;					\
+      __asm__ ("fcmp%.x %2,%1; fsoge %0"		\
+	       : "=dm" (__result) : "f" (x), "f" (y));	\
+      __result != 0; })
+
+# define isless(x, y)					\
+   __extension__					\
+   ({ char __result;					\
+      __asm__ ("fcmp%.x %2,%1; fsolt %0"		\
+	       : "=dm" (__result) : "f" (x), "f" (y));	\
+      __result != 0; })
+
+# define islessequal(x, y)				\
+   __extension__					\
+   ({ char __result;					\
+      __asm__ ("fcmp%.x %2,%1; fsole %0"		\
+	       : "=dm" (__result) : "f" (x), "f" (y));	\
+      __result != 0; })
+
+# define islessgreater(x, y)				\
+   __extension__					\
+   ({ char __result;					\
+      __asm__ ("fcmp%.x %2,%1; fsogl %0"		\
+	       : "=dm" (__result) : "f" (x), "f" (y));	\
+      __result != 0; })
+
+# define isunordered(x, y)				\
+   __extension__					\
+   ({ char __result;					\
+      __asm__ ("fcmp%.x %2,%1; fsun %0"			\
+	       : "=dm" (__result) : "f" (x), "f" (y));	\
+      __result != 0; })
+#endif
+
+
+#if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
+    || defined __LIBC_INTERNAL_MATH_INLINES
+
+#ifdef	__LIBC_INTERNAL_MATH_INLINES
+/* This is used when defining the functions themselves.  Define them with
+   __ names, and with `static inline' instead of `extern inline' so the
+   bodies will always be used, never an external function call.  */
+# define __m81_u(x)		__CONCAT(__,x)
+# define __m81_inline		static __inline
+#else
+# define __m81_u(x)		x
+# ifdef __cplusplus
+#  define __m81_inline		__inline
+# else
+#  define __m81_inline		extern __inline
+# endif
+# define __M81_MATH_INLINES	1
+#endif
+
+/* Define a const math function.  */
+#define __m81_defun(rettype, func, args)				      \
+  __m81_inline rettype __attribute__((__const__))			      \
+  __m81_u(func) args
+
+/* Define the three variants of a math function that has a direct
+   implementation in the csky fpu.  FUNC is the name for C (which will be
+   suffixed with f and l for the float and long double version, resp).  OP
+   is the name of the fpu operation (without leading f).  */
+
+#if defined __USE_MISC || defined __USE_ISOC99
+# define __inline_mathop(func, op)			\
+  __inline_mathop1(double, func, op)			\
+  __inline_mathop1(float, __CONCAT(func,f), op)		\
+  __inline_mathop1(long double, __CONCAT(func,l), op)
+#else
+# define __inline_mathop(func, op)			\
+  __inline_mathop1(double, func, op)
+#endif
+
+#define __inline_mathop1(float_type,func, op)				      \
+  __m81_defun (float_type, func, (float_type __mathop_x)) __THROW	      \
+  {									      \
+    float_type __result;						      \
+    __asm("f" __STRING(op) "%.x %1, %0" : "=f" (__result) : "f" (__mathop_x));\
+    return __result;							      \
+  }
+
+__inline_mathop(__atan, atan)
+__inline_mathop(__cos, cos)
+__inline_mathop(__sin, sin)
+__inline_mathop(__tan, tan)
+__inline_mathop(__tanh, tanh)
+__inline_mathop(__fabs, abs)
+
+#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
+__inline_mathop(__rint, int)
+__inline_mathop(__expm1, etoxm1)
+__inline_mathop(__log1p, lognp1)
+#endif
+
+#ifdef __USE_MISC
+__inline_mathop(__significand, getman)
+#endif
+
+#ifdef __USE_ISOC99
+__inline_mathop(__trunc, intrz)
+#endif
+
+#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
+
+__inline_mathop(atan, atan)
+__inline_mathop(cos, cos)
+__inline_mathop(sin, sin)
+__inline_mathop(tan, tan)
+__inline_mathop(tanh, tanh)
+
+# if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
+__inline_mathop(rint, int)
+__inline_mathop(expm1, etoxm1)
+__inline_mathop(log1p, lognp1)
+# endif
+
+# ifdef __USE_MISC
+__inline_mathop(significand, getman)
+# endif
+
+# ifdef __USE_ISOC99
+__inline_mathop(trunc, intrz)
+# endif
+
+#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
+
+/* This macro contains the definition for the rest of the inline
+   functions, using FLOAT_TYPE as the domain type and S as the suffix
+   for the function names.  */
+
+#define __inline_functions(float_type, s)				  \
+__m81_inline float_type							  \
+__m81_u(__CONCAT(__frexp,s))(float_type __value, int *__expptr)	__THROW	  \
+{									  \
+  float_type __mantissa, __exponent;					  \
+  int __iexponent;							  \
+  unsigned long __fpsr;							  \
+  __asm("ftst%.x %1\n"							  \
+	"fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));	  \
+  if (__fpsr & (7 << 24))						  \
+    {									  \
+      /* Not finite or zero.  */					  \
+      *__expptr = 0;							  \
+      return __value;							  \
+    }									  \
+  __asm("fgetexp%.x %1, %0" : "=f" (__exponent) : "f" (__value));	  \
+  __iexponent = (int) __exponent + 1;					  \
+  *__expptr = __iexponent;						  \
+  __asm("fscale%.l %2, %0" : "=f" (__mantissa)				  \
+	: "0" (__value), "dmi" (-__iexponent));				  \
+  return __mantissa;							  \
+}									  \
+									  \
+__m81_defun (float_type, __CONCAT(__floor,s), (float_type __x))	__THROW	  \
+{									  \
+  float_type __result;							  \
+  unsigned long int __ctrl_reg;						  \
+  __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));		  \
+  /* Set rounding towards negative infinity.  */			  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" ((__ctrl_reg & ~0x10) | 0x20));		  \
+  /* Convert X to an integer, using -Inf rounding.  */			  \
+  __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));	  \
+  /* Restore the previous rounding mode.  */				  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" (__ctrl_reg));				  \
+  return __result;							  \
+}									  \
+									  \
+__m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x)) __THROW	  \
+{									  \
+  float_type __result;							  \
+  unsigned long int __ctrl_reg;						  \
+  __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));		  \
+  /* Set rounding towards positive infinity.  */			  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" (__ctrl_reg | 0x30));			  \
+  /* Convert X to an integer, using +Inf rounding.  */			  \
+  __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));	  \
+  /* Restore the previous rounding mode.  */				  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" (__ctrl_reg));				  \
+  return __result;							  \
+}
+
+__inline_functions(double,)
+#if defined __USE_MISC || defined __USE_ISOC99
+__inline_functions(float,f)
+__inline_functions(long double,l)
+#endif
+#undef __inline_functions
+
+#ifdef __USE_MISC
+
+# define __inline_functions(float_type, s)				  \
+__m81_defun (int, __CONCAT(__isinf,s), (float_type __value)) __THROW	  \
+{									  \
+  /* There is no branch-condition for infinity,				  \
+     so we must extract and examine the condition codes manually.  */	  \
+  unsigned long int __fpsr;						  \
+  __asm("ftst%.x %1\n"							  \
+	"fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));	  \
+  return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0;	  \
+}									  \
+									  \
+__m81_defun (int, __CONCAT(__finite,s), (float_type __value)) __THROW	  \
+{									  \
+  /* There is no branch-condition for infinity, so we must extract and	  \
+     examine the condition codes manually.  */				  \
+  unsigned long int __fpsr;						  \
+  __asm ("ftst%.x %1\n"							  \
+	 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));	  \
+  return (__fpsr & (3 << 24)) == 0;					  \
+}									  \
+									  \
+__m81_defun (float_type, __CONCAT(__scalbn,s),				  \
+	     (float_type __x, int __n))	__THROW				  \
+{									  \
+  float_type __result;							  \
+  __asm ("fscale%.l %1, %0" : "=f" (__result) : "dmi" (__n), "0" (__x));  \
+  return __result;							  \
+}
+
+__inline_functions(double,)
+__inline_functions(float,f)
+__inline_functions(long double,l)
+# undef __inline_functions
+
+#endif /* Use misc.  */
+
+#if defined __USE_MISC || defined __USE_XOPEN
+
+# define __inline_functions(float_type, s)				  \
+__m81_defun (int, __CONCAT(__isnan,s), (float_type __value)) __THROW	  \
+{									  \
+  char __result;							  \
+  __asm("ftst%.x %1\n"							  \
+	"fsun %0" : "=dm" (__result) : "f" (__value));			  \
+  return __result;							  \
+}
+
+__inline_functions(double,)
+# ifdef __USE_MISC
+__inline_functions(float,f)
+__inline_functions(long double,l)
+# endif
+# undef __inline_functions
+
+#endif
+
+#ifdef __USE_ISOC99
+
+# define __inline_functions(float_type, s)				  \
+__m81_defun (int, __CONCAT(__signbit,s), (float_type __value)) __THROW	  \
+{									  \
+  /* There is no branch-condition for the sign bit, so we must extract	  \
+     and examine the condition codes manually.  */			  \
+  unsigned long int __fpsr;						  \
+  __asm ("ftst%.x %1\n"							  \
+	 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));	  \
+  return (__fpsr >> 27) & 1;						  \
+}									  \
+									  \
+__m81_defun (float_type, __CONCAT(__scalbln,s),				  \
+	     (float_type __x, long int __n)) __THROW			  \
+{									  \
+  return __CONCAT(__scalbn,s) (__x, __n);				  \
+}									  \
+									  \
+__m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x)) __THROW \
+{									  \
+  float_type __result;							  \
+  unsigned long int __ctrl_reg;						  \
+  __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));		  \
+  /* Temporarily disable the inexact exception.  */			  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" (__ctrl_reg & ~0x200));			  \
+  __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));	  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" (__ctrl_reg));				  \
+  return __result;							  \
+}									  \
+									  \
+__m81_defun (long int, __CONCAT(__lrint,s), (float_type __x)) __THROW	  \
+{									  \
+  long int __result;							  \
+  __asm ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x));		  \
+  return __result;							  \
+}									  \
+									  \
+__m81_inline float_type							  \
+__m81_u(__CONCAT(__fma,s))(float_type __x, float_type __y,		  \
+			   float_type __z) __THROW			  \
+{									  \
+  return (__x * __y) + __z;						  \
+}
+
+__inline_functions (double,)
+__inline_functions (float,f)
+__inline_functions (long double,l)
+# undef __inline_functions
+
+#endif /* Use ISO C9x */
+
+#ifdef __USE_GNU
+
+# define __inline_functions(float_type, s)				\
+__m81_inline void							\
+__m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx,	\
+			      float_type *__cosx) __THROW		\
+{									\
+  __asm ("fsincos%.x %2,%1:%0"						\
+	 : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x));			\
+}
+
+__inline_functions (double,)
+__inline_functions (float,f)
+__inline_functions (long double,l)
+# undef __inline_functions
+
+#endif
+
+#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
+
+/* Define inline versions of the user visible functions.  */
+
+/* Note that there must be no whitespace before the argument passed for
+   NAME, to make token pasting work correctly with -traditional.  */
+# define __inline_forward_c(rettype, name, args1, args2)	\
+extern __inline rettype __attribute__((__const__))	\
+name args1 __THROW					\
+{							\
+  return __CONCAT(__,name) args2;			\
+}
+
+# define __inline_forward(rettype, name, args1, args2)	\
+extern __inline rettype name args1 __THROW		\
+{							\
+  return __CONCAT(__,name) args2;			\
+}
+
+__inline_forward(double,frexp, (double __value, int *__expptr),
+		 (__value, __expptr))
+__inline_forward_c(double,floor, (double __x), (__x))
+__inline_forward_c(double,ceil, (double __x), (__x))
+# ifdef __USE_MISC
+#  ifndef __USE_ISOC99 /* Conflict with macro of same name.  */
+__inline_forward_c(int,isinf, (double __value), (__value))
+#  endif
+__inline_forward_c(int,finite, (double __value), (__value))
+__inline_forward_c(double,scalbn, (double __x, int __n), (__x, __n))
+# endif
+# if defined __USE_MISC || defined __USE_XOPEN
+#  ifndef __USE_ISOC99 /* Conflict with macro of same name.  */
+__inline_forward_c(int,isnan, (double __value), (__value))
+#  endif
+# endif
+# ifdef __USE_ISOC99
+__inline_forward_c(double,scalbln, (double __x, long int __n), (__x, __n))
+__inline_forward_c(double,nearbyint, (double __value), (__value))
+__inline_forward_c(long int,lrint, (double __value), (__value))
+__inline_forward_c(double,fma, (double __x, double __y, double __z),
+		   (__x, __y, __z))
+# endif
+# ifdef __USE_GNU
+__inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx),
+		 (__x, __sinx, __cosx))
+# endif
+
+# if defined __USE_MISC || defined __USE_ISOC99
+
+__inline_forward(float,frexpf, (float __value, int *__expptr),
+		 (__value, __expptr))
+__inline_forward_c(float,floorf, (float __x), (__x))
+__inline_forward_c(float,ceilf, (float __x), (__x))
+#  ifdef __USE_MISC
+__inline_forward_c(int,isinff, (float __value), (__value))
+__inline_forward_c(int,finitef, (float __value), (__value))
+__inline_forward_c(float,scalbnf, (float __x, int __n), (__x, __n))
+__inline_forward_c(int,isnanf, (float __value), (__value))
+#  endif
+# ifdef __USE_ISOC99
+__inline_forward_c(float,scalblnf, (float __x, long int __n), (__x, __n))
+__inline_forward_c(float,nearbyintf, (float __value), (__value))
+__inline_forward_c(long int,lrintf, (float __value), (__value))
+__inline_forward_c(float,fmaf, (float __x, float __y, float __z),
+		   (__x, __y, __z))
+# endif
+# ifdef __USE_GNU
+__inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx),
+		 (__x, __sinx, __cosx))
+# endif
+
+__inline_forward(long double,frexpl, (long double __value, int *__expptr),
+		 (__value, __expptr))
+__inline_forward_c(long double,floorl, (long double __x), (__x))
+__inline_forward_c(long double,ceill, (long double __x), (__x))
+# ifdef __USE_MISC
+__inline_forward_c(int,isinfl, (long double __value), (__value))
+__inline_forward_c(int,finitel, (long double __value), (__value))
+__inline_forward_c(long double,scalbnl, (long double __x, int __n), (__x, __n))
+__inline_forward_c(int,isnanl, (long double __value), (__value))
+# endif
+# ifdef __USE_ISOC99
+__inline_forward_c(long double,scalblnl, (long double __x, long int __n),
+		   (__x, __n))
+__inline_forward_c(long double,nearbyintl, (long double __value), (__value))
+__inline_forward_c(long int,lrintl, (long double __value), (__value))
+__inline_forward_c(long double,fmal,
+		   (long double __x, long double __y, long double __z),
+		   (__x, __y, __z))
+# endif
+# ifdef __USE_GNU
+__inline_forward(void,sincosl,
+		 (long double __x, long double *__sinx, long double *__cosx),
+		 (__x, __sinx, __cosx))
+# endif
+
+#endif /* Use misc or ISO C99 */
+
+#undef __inline_forward
+#undef __inline_forward_c
+
+#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
+
+#endif
+#endif
diff --git a/libc/sysdeps/linux/csky/bits/setjmp.h b/libc/sysdeps/linux/csky/bits/setjmp.h
new file mode 100644
index 0000000..c818ec9
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/setjmp.h
@@ -0,0 +1,19 @@ 
+#ifndef _BITS_SETJMP_H
+#define _BITS_SETJMP_H	1
+
+#if !defined _SETJMP_H  && !defined _PTHREAD_H
+# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
+#endif
+
+typedef struct
+{
+  unsigned long __sp; /* the return stack address */
+  unsigned long __pc; /* pc: r15, return address */
+  /*
+   * ABIV1 is r8~r14
+   * ABIV2 is r4~r11, r16~r17, r26~r31
+   */
+  unsigned long __regs[16];
+} __jmp_buf[1];
+
+#endif /* _BITS_SETJMP_H */
diff --git a/libc/sysdeps/linux/csky/bits/shm.h b/libc/sysdeps/linux/csky/bits/shm.h
new file mode 100644
index 0000000..bfb44bb
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/shm.h
@@ -0,0 +1,85 @@ 
+#ifndef _SYS_SHM_H
+# error "Never include <bits/shm.h> directly; use <sys/shm.h> instead."
+#endif
+
+#include <bits/types.h>
+
+/* Permission flag for shmget.  */
+#define SHM_R		0400		/* or S_IRUGO from <linux/stat.h> */
+#define SHM_W		0200		/* or S_IWUGO from <linux/stat.h> */
+
+/* Flags for `shmat'.  */
+#define SHM_RDONLY	010000		/* attach read-only else read-write */
+#define SHM_RND		020000		/* round attach address to SHMLBA */
+#define SHM_REMAP	040000		/* take-over region on attach */
+
+/* Commands for `shmctl'.  */
+#define SHM_LOCK	11		/* lock segment (root only) */
+#define SHM_UNLOCK	12		/* unlock segment (root only) */
+
+__BEGIN_DECLS
+
+/* Segment low boundary address multiple.  */
+#define SHMLBA		(__getpagesize () << 2)
+extern int __getpagesize (void) __THROW __attribute__ ((__const__));
+
+
+/* Type to count number of attaches.  */
+typedef unsigned long int shmatt_t;
+
+/* Data structure describing a set of semaphores.  */
+struct shmid_ds
+  {
+    struct ipc_perm shm_perm;		/* operation permission struct */
+    size_t shm_segsz;			/* size of segment in bytes */
+    __time_t shm_atime;			/* time of last shmat() */
+    unsigned long int __unused1;
+    __time_t shm_dtime;			/* time of last shmdt() */
+    unsigned long int __unused2;
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+    unsigned long int __unused3;
+    __pid_t shm_cpid;			/* pid of creator */
+    __pid_t shm_lpid;			/* pid of last shmop */
+    shmatt_t shm_nattch;		/* number of current attaches */
+    unsigned long int __unused4;
+    unsigned long int __unused5;
+  };
+
+#ifdef __USE_MISC
+
+/* ipcs ctl commands */
+# define SHM_STAT 	13
+# define SHM_INFO 	14
+
+/* shm_mode upper byte flags */
+# define SHM_DEST	01000	/* segment will be destroyed on last detach */
+# define SHM_LOCKED	02000   /* segment will not be swapped */
+# define SHM_HUGETLB	04000	/* segment is mapped via hugetlb */
+# define SHM_NORESERVE	010000	/* don't check for reservations */
+
+struct	shminfo
+  {
+    unsigned long int shmmax;
+    unsigned long int shmmin;
+    unsigned long int shmmni;
+    unsigned long int shmseg;
+    unsigned long int shmall;
+    unsigned long int __unused1;
+    unsigned long int __unused2;
+    unsigned long int __unused3;
+    unsigned long int __unused4;
+  };
+
+struct shm_info
+  {
+    int used_ids;
+    unsigned long int shm_tot;	/* total allocated shm */
+    unsigned long int shm_rss;	/* total resident shm */
+    unsigned long int shm_swp;	/* total swapped shm */
+    unsigned long int swap_attempts;
+    unsigned long int swap_successes;
+  };
+
+#endif /* __USE_MISC */
+
+__END_DECLS
diff --git a/libc/sysdeps/linux/csky/bits/sigcontextinfo.h b/libc/sysdeps/linux/csky/bits/sigcontextinfo.h
new file mode 100644
index 0000000..b7e08cf
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/sigcontextinfo.h
@@ -0,0 +1,26 @@ 
+/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define SIGCONTEXT int _code, struct sigcontext *
+#define SIGCONTEXT_EXTRA_ARGS _code,
+#define GET_PC(ctx)	((void *) (ctx)->sc_pc)
+#define GET_FRAME(ctx)	((void *) __builtin_frame_address (1))
+#define GET_STACK(ctx)	((void *) (ctx)->sc_usp)
+#define CALL_SIGHANDLER(handler, signo, ctx) \
+  (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx))
diff --git a/libc/sysdeps/linux/csky/bits/stackinfo.h b/libc/sysdeps/linux/csky/bits/stackinfo.h
new file mode 100644
index 0000000..aaf9807
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/stackinfo.h
@@ -0,0 +1,6 @@ 
+#ifndef _STACKINFO_H
+#define _STACKINFO_H	1
+
+#define _STACK_GROWS_DOWN	1
+
+#endif
diff --git a/libc/sysdeps/linux/csky/bits/syscalls.h b/libc/sysdeps/linux/csky/bits/syscalls.h
new file mode 100644
index 0000000..04d01f4
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/syscalls.h
@@ -0,0 +1,113 @@ 
+#ifndef _BITS_SYSCALLS_H
+#define _BITS_SYSCALLS_H
+#ifndef _SYSCALL_H
+# error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
+#endif
+
+#undef __NR_iopl
+#undef __NR_vm86
+
+/*
+   Some of the sneaky macros in the code were taken from
+   glibc-2.3.2/sysdeps/unix/sysv/linux/arm/sysdep.h
+*/
+
+//#include <errno.h>
+
+#define INLINE_SYSCALL_NCS(name, nr, args...)				\
+(__extension__								\
+  ({									\
+     unsigned int _inline_sys_result = INTERNAL_SYSCALL_NCS (name, , nr, args);\
+     if (unlikely (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, )))	\
+       {								\
+	 __set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, ));	\
+	 _inline_sys_result = (unsigned int) -1;			\
+       }								\
+     (int) _inline_sys_result;						\
+   })									\
+)
+
+#undef INTERNAL_SYSCALL_NCS
+#ifndef __cskyabiv2__
+#define INTERNAL_SYSCALL_NCS(name, err, nr, args...)                        \
+  ({unsigned int __sys_result;                                          \
+     {                                                                  \
+       register int _a1 __asm__ ("a0"), _nr __asm__ ("r1");             \
+       LOAD_ARGS_##nr (args)                                            \
+       _nr = (name);                                             \
+       __asm__ __volatile__ ("trap  0 \n\t"                             \
+                             : "=r" (_a1)                               \
+                             : "r" (_nr) ASM_ARGS_##nr                  \
+                             : "memory");                               \
+               __sys_result = _a1;                                      \
+     }                                                                  \
+     (int) __sys_result; })
+
+#else /* __cskyabiv2__ */
+#define INTERNAL_SYSCALL_NCS(name, err, nr, args...)                        \
+  ({unsigned int __sys_result;                                          \
+     {                                                                  \
+       register int _a1 __asm__ ("a0"), _nr __asm__ ("r7");             \
+       LOAD_ARGS_##nr (args)                                            \
+       _nr = (name);                                             \
+       __asm__ __volatile__ ("trap  0    \n\t"                          \
+                             : "=r" (_a1)                               \
+                             : "r" (_nr) ASM_ARGS_##nr                  \
+                             : "memory");                               \
+               __sys_result = _a1;                                      \
+     }                                                                  \
+     (int) __sys_result; })
+#endif /* __ABI_CSKY_V2__ */
+
+#define INTERNAL_SYSCALL_ERROR_P(val, err) \
+  ((unsigned int) (val) >= 0xfffff001u)
+
+#define LOAD_ARGS_0()
+#define ASM_ARGS_0
+#define LOAD_ARGS_1(a1)                         \
+  _a1 = (int) (a1);                             \
+  LOAD_ARGS_0 ()
+#define ASM_ARGS_1      ASM_ARGS_0, "r" (_a1)
+#define LOAD_ARGS_2(a1, a2)                     \
+  register int _a2 __asm__ ("a1") = (int) (a2); \
+  LOAD_ARGS_1 (a1)
+#define ASM_ARGS_2      ASM_ARGS_1, "r" (_a2)
+#define LOAD_ARGS_3(a1, a2, a3)                 \
+  register int _a3 __asm__ ("a2") = (int) (a3); \
+  LOAD_ARGS_2 (a1, a2)
+#define ASM_ARGS_3      ASM_ARGS_2, "r" (_a3)
+#define LOAD_ARGS_4(a1, a2, a3, a4)             \
+  register int _a4 __asm__ ("a3") = (int) (a4); \
+  LOAD_ARGS_3 (a1, a2, a3)
+#define ASM_ARGS_4      ASM_ARGS_3, "r" (_a4)
+
+#ifndef __cskyabiv2__
+#define LOAD_ARGS_5(a1, a2, a3, a4, a5)         \
+  register int _v1 __asm__ ("a4") = (int) (a5); \
+  LOAD_ARGS_4 (a1, a2, a3, a4)
+#define ASM_ARGS_5      ASM_ARGS_4, "r" (_v1)
+#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)     \
+  register int _v2 __asm__ ("a5") = (int) (a6); \
+  LOAD_ARGS_5 (a1, a2, a3, a4, a5)
+#define ASM_ARGS_6      ASM_ARGS_5, "r" (_v2)
+#define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7) \
+  register int _v3 __asm__ ("r8") = (int) (a7); \
+  LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6)
+#define ASM_ARGS_7      ASM_ARGS_6, "r" (_v3)
+#else /* __cskyabiv2__ */
+#define LOAD_ARGS_5(a1, a2, a3, a4, a5)         \
+  register int _v1 __asm__ ("l0") = (int) (a5); \
+  LOAD_ARGS_4 (a1, a2, a3, a4)
+#define ASM_ARGS_5      ASM_ARGS_4, "r" (_v1)
+#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)     \
+  register int _v2 __asm__ ("l1") = (int) (a6); \
+  LOAD_ARGS_5 (a1, a2, a3, a4, a5)
+#define ASM_ARGS_6      ASM_ARGS_5, "r" (_v2)
+#define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7) \
+  register int _v3 __asm__ ("l2") = (int) (a7); \
+  LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6)
+#define ASM_ARGS_7      ASM_ARGS_6, "r" (_v3)
+#endif /* __ABI_CSKY_V2__ */
+
+
+#endif /* _BITS_SYSCALLS_H */
diff --git a/libc/sysdeps/linux/csky/bits/uClibc_arch_features.h b/libc/sysdeps/linux/csky/bits/uClibc_arch_features.h
new file mode 100644
index 0000000..ca898ee
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/uClibc_arch_features.h
@@ -0,0 +1,46 @@ 
+/*
+ * Track misc arch-specific features that aren't config options
+ */
+
+#ifndef _BITS_UCLIBC_ARCH_FEATURES_H
+#define _BITS_UCLIBC_ARCH_FEATURES_H
+
+# define __UCLIBC_ABORT_INSTRUCTION__ ".long 0xffffffff"
+
+/* can your target use syscall6() for mmap ? */
+#undef __UCLIBC_MMAP_HAS_6_ARGS__
+
+#ifdef __CSKYABIV2__
+#undef __UCLIBC_SYSCALL_ALIGN_64BIT__
+#else
+#define __UCLIBC_SYSCALL_ALIGN_64BIT__
+#endif
+
+/* does your target have a broken create_module() ? */
+#define __UCLIBC_BROKEN_CREATE_MODULE__
+
+/* does your target have to worry about older [gs]etrlimit() ? */
+#define __UCLIBC_HANDLE_OLDER_RLIMIT__
+
+/* does your target have an asm .set ? */
+#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__
+
+/* define if target doesn't like .global */
+#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__
+
+/* define if target supports .weak */
+#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__
+
+/* define if target supports .weakext */
+#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__
+
+/* needed probably only for ppc64 */
+#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__
+
+/* define if target supports IEEE signed zero floats */
+#define __UCLIBC_HAVE_SIGNED_ZERO__
+
+/* define if target supports CFI pseudo ops */
+#define __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__
+
+#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */
diff --git a/libc/sysdeps/linux/csky/bits/wordsize.h b/libc/sysdeps/linux/csky/bits/wordsize.h
new file mode 100644
index 0000000..1b5842a
--- /dev/null
+++ b/libc/sysdeps/linux/csky/bits/wordsize.h
@@ -0,0 +1 @@ 
+#define __WORDSIZE	32
diff --git a/libc/sysdeps/linux/csky/cacheflush.c b/libc/sysdeps/linux/csky/cacheflush.c
new file mode 100644
index 0000000..7762c73
--- /dev/null
+++ b/libc/sysdeps/linux/csky/cacheflush.c
@@ -0,0 +1,2 @@ 
+#include <sys/syscall.h>
+_syscall3(int, cacheflush, void *, addr, int, nbytes, int, op)
diff --git a/libc/sysdeps/linux/csky/clone.c b/libc/sysdeps/linux/csky/clone.c
new file mode 100644
index 0000000..97c30d0
--- /dev/null
+++ b/libc/sysdeps/linux/csky/clone.c
@@ -0,0 +1,47 @@ 
+#include <stdarg.h>
+#include <sysdep.h>
+#include <unistd.h>
+
+extern int __syscall_error(int err_no);
+
+extern int __csky_clone (
+  int flags,
+  void *child_stack,
+  pid_t *ptid,
+  pid_t *ctid,
+  void *tls);
+
+int __clone(
+  int (*fn)(void *),
+  void *child_stack,
+  int flags,
+  void *arg, ...)
+{
+  void *ptid;
+  void *tls;
+  void *ctid;
+  va_list al;
+  int err;
+
+  va_start(al, arg);
+  ptid = va_arg(al, void *);
+  tls = va_arg(al, void *);
+  ctid = va_arg(al, void *);
+  va_end(al);
+
+  err = EINVAL;
+  if (!fn)
+    goto err;
+  if (!child_stack)
+    goto err;
+
+  /* prepare fn&arg in child_stack */
+  child_stack = (void *)((unsigned int)child_stack - 8);
+  *(unsigned int *)child_stack = (unsigned int)fn;
+  *(unsigned int *)(child_stack + 4) = (unsigned int)arg;
+
+  return __csky_clone(flags, child_stack, ptid, ctid, tls);
+err:
+  return __syscall_error(-err);
+}
+weak_alias(__clone, clone)
diff --git a/libc/sysdeps/linux/csky/crt1.S b/libc/sysdeps/linux/csky/crt1.S
new file mode 100644
index 0000000..ae73843
--- /dev/null
+++ b/libc/sysdeps/linux/csky/crt1.S
@@ -0,0 +1,95 @@ 
+#include <sysdep.h>
+
+ .text
+.global	_start
+.type   _start,%function
+.global __exit
+.global atexit
+
+.global _init
+.global _fini
+
+.global main
+.global __uClibc_main
+
+/*
+ * argc, argv and envp are on the stack
+ *
+ * Call:
+ * void __uClibc_main(
+ *         int (*main)(int, char **, char **),
+ *         int argc,
+ *         char **argv,
+ *         void (*app_init)(void),
+ *         void (*app_fini)(void),
+ *         void (*rtld_fini)(void),
+ *         void *stack_end attribute_unused);
+ */
+
+_start:
+#ifdef __PIC__
+	__GET_GB
+	lrw	a0, main@GOT
+	addu	a0, gb
+	ldw	a0, (a0)
+
+	ldw	a1, (sp)
+	mov	a2, sp
+	addi	a2, 4
+
+	mov	a3, sp /* push stack_end */
+	subi	sp, 8
+	stw	a3, (sp)
+
+	lrw	a3, _init@GOT
+	addu	a3, gb
+	ldw	a3, (a3)
+
+#ifdef __CSKYABIV2__
+	subi	sp, 8
+	lrw	l4, _fini@GOT
+	addu	l4, gb
+	ldw	l4, (l4)
+	stw	l4, (sp)
+
+	stw	r7, (sp, 4) /* push rtld_fini */
+#else
+	lrw	a4, _fini@GOT
+	addu	a4, gb
+	ldw	a4, (a4)
+#endif
+
+	lrw	l4,  __uClibc_main@PLT
+	addu	l4, gb
+	ldw	l4, (l4)
+	jsr	l4
+
+#else /* __PIC__ */
+	lrw	a0, main
+
+	ldw	a1, (sp)
+	mov	a2, sp
+	addi	a2, 4
+
+	mov	a3, sp     /* push stack_end */
+	subi	sp, 8
+	stw	a3, (sp)
+
+	lrw	a3, _init
+#ifdef __CSKYABIV2__
+	subi	sp, 8
+	lrw	l4, _fini
+	stw	l4, (sp)
+	stw	r7, (sp, 4)
+#else
+	lrw	a4, _fini
+#endif
+
+	lrw	l4, __uClibc_main
+	jsr	l4
+#endif /* __PIC__ */
+	bsr	__exit
+__exit:
+	DO_CALL(exit, 0)
+	br .
+
diff --git a/libc/sysdeps/linux/csky/crti.S b/libc/sysdeps/linux/csky/crti.S
new file mode 100644
index 0000000..e85a81c
--- /dev/null
+++ b/libc/sysdeps/linux/csky/crti.S
@@ -0,0 +1,13 @@ 
+#include <sysdep.h>
+.file  "initfini.c"
+
+.section .init
+ENTRY(_init)
+	subi	sp, 8
+	stw	lr, (sp, 4)
+
+.section .fini
+ENTRY(_fini)
+	subi	sp, 8
+	stw	lr, (sp, 4)
+
diff --git a/libc/sysdeps/linux/csky/crtn.S b/libc/sysdeps/linux/csky/crtn.S
new file mode 100644
index 0000000..3814f30
--- /dev/null
+++ b/libc/sysdeps/linux/csky/crtn.S
@@ -0,0 +1,11 @@ 
+.file  "initfini.c"
+
+.section .init
+	ldw	lr, (sp, 4)
+	addi	sp, 8
+	rts
+
+.section .fini
+	ldw	lr, (sp, 4)
+	addi	sp, 8
+	rts
diff --git a/libc/sysdeps/linux/csky/csky_clone.S b/libc/sysdeps/linux/csky/csky_clone.S
new file mode 100644
index 0000000..8360469
--- /dev/null
+++ b/libc/sysdeps/linux/csky/csky_clone.S
@@ -0,0 +1,20 @@ 
+#include <sysdep.h>
+
+PSEUDO_ERRVAL(__csky_clone, clone, 5)
+  cmpnei a0, 0
+  bf start_thread
+  rts
+
+start_thread:
+#ifdef  __CSKYABIV2__
+  subi	sp, 4
+#endif
+  ld.w	a0, (sp, 0x4)
+  ld.w	a1, (sp, 0x0)
+  addi	sp, 8
+  jsr   a1
+
+  DO_CALL(exit, 0)
+
+END(__csky_clone)
+
diff --git a/libc/sysdeps/linux/csky/jmpbuf-unwind.h b/libc/sysdeps/linux/csky/jmpbuf-unwind.h
new file mode 100644
index 0000000..30e39f4
--- /dev/null
+++ b/libc/sysdeps/linux/csky/jmpbuf-unwind.h
@@ -0,0 +1,15 @@ 
+#include <setjmp.h>
+#include <stdint.h>
+#include <unwind.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+   containing a local variable at ADDRESS.  */
+#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
+  ((void *) (address) < (void *) demangle (jmpbuf[0].__sp))
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf[0].__sp) - (_adj))
+
diff --git a/libc/sysdeps/linux/csky/libc-read_tp.S b/libc/sysdeps/linux/csky/libc-read_tp.S
new file mode 100644
index 0000000..1974cba
--- /dev/null
+++ b/libc/sysdeps/linux/csky/libc-read_tp.S
@@ -0,0 +1 @@ 
+#include <ldso/ldso/csky/read_tp.S>
diff --git a/libc/sysdeps/linux/csky/setjmp.S b/libc/sysdeps/linux/csky/setjmp.S
new file mode 100644
index 0000000..daadcb3
--- /dev/null
+++ b/libc/sysdeps/linux/csky/setjmp.S
@@ -0,0 +1,43 @@ 
+#include <sysdep.h>
+
+ENTRY(setjmp)
+	stw     sp, (a0, 0)
+	stw     lr, (a0, 4)
+
+	stw     l0, (a0, 8)
+	stw     l1, (a0, 12)
+	stw     l2, (a0, 16)
+	stw     l3, (a0, 20)
+	stw     l4, (a0, 24)
+	stw     l5, (a0, 28)
+
+#ifdef __CSKYABIV2__
+	stw	l6, (a0, 32)
+        stw	l7, (a0, 36)
+        stw	l8, (a0, 40)
+        stw	l9, (a0, 44)
+
+        stw	r26, (a0, 48)
+        stw	r27, (a0, 52)
+        stw	gb,  (a0, 56)
+        stw	r29, (a0, 60)
+        stw	r30, (a0, 64)
+        stw	tls, (a0, 68)
+#else
+	stw     gb, (a0, 32)
+#endif
+
+	subi	sp, 8
+	stw	lr, (sp, 0)
+	stw     gb, (sp, 4)
+	__GET_GB
+	__JSR(__sigjmp_save)
+	ldw     gb, (sp, 4)
+	ldw	lr, (sp, 0)
+	addi	sp, 8
+	rts
+END(setjmp)
+
+strong_alias(setjmp, __sigsetjmp)
+strong_alias(setjmp, _setjmp)
+
diff --git a/libc/sysdeps/linux/csky/sys/cachectl.h b/libc/sysdeps/linux/csky/sys/cachectl.h
new file mode 100644
index 0000000..0d45bf0
--- /dev/null
+++ b/libc/sysdeps/linux/csky/sys/cachectl.h
@@ -0,0 +1,10 @@ 
+#ifndef _SYS_CACHECTL_H
+#define _SYS_CACHECTL_H	1
+
+#include <asm/cachectl.h>
+
+__BEGIN_DECLS
+extern int cacheflush(void *addr, int nbytes, int flags);
+__END_DECLS
+
+#endif
diff --git a/libc/sysdeps/linux/csky/sys/procfs.h b/libc/sysdeps/linux/csky/sys/procfs.h
new file mode 100644
index 0000000..91c1388
--- /dev/null
+++ b/libc/sysdeps/linux/csky/sys/procfs.h
@@ -0,0 +1,126 @@ 
+/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _SYS_PROCFS_H
+#define _SYS_PROCFS_H	1
+
+/* This is somewhat modelled after the file of the same name on SVR4
+   systems.  It provides a definition of the core file format for ELF
+   used on Linux.  It doesn't have anything to do with the /proc file
+   system, even though Linux has one.
+
+   Anyway, the whole purpose of this file is for GDB and GDB only.
+   Don't read too much into it.  Don't use it for anything other than
+   GDB unless you know what you are doing.  */
+
+#include <features.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/user.h>
+
+__BEGIN_DECLS
+
+/* Type for a general-purpose register.  */
+typedef unsigned long elf_greg_t;
+
+/* And the whole bunch of them.  We could have used `struct
+   user_regs' directly in the typedef, but tradition says that
+   the register set is an array, which does have some peculiar
+   semantics, so leave it that way.  */
+#define ELF_NGREG (sizeof (struct user_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* Register set for the floating-point registers.  */
+typedef struct user_fpregs elf_fpregset_t;
+
+
+/* Signal info.  */
+struct elf_siginfo
+  {
+    int si_signo;			/* Signal number.  */
+    int si_code;			/* Extra code.  */
+    int si_errno;			/* Errno.  */
+  };
+
+
+/* Definitions to generate Intel SVR4-like core files.  These mostly
+   have the same names as the SVR4 types with "elf_" tacked on the
+   front to prevent clashes with Linux definitions, and the typedef
+   forms have been avoided.  This is mostly like the SVR4 structure,
+   but more Linuxy, with things that Linux does not support and which
+   GDB doesn't really use excluded.  */
+
+struct elf_prstatus
+  {
+    struct elf_siginfo pr_info;		/* Info associated with signal.  */
+    short int pr_cursig;		/* Current signal.  */
+    unsigned long int pr_sigpend;	/* Set of pending signals.  */
+    unsigned long int pr_sighold;	/* Set of held signals.  */
+    __pid_t pr_pid;
+    __pid_t pr_ppid;
+    __pid_t pr_pgrp;
+    __pid_t pr_sid;
+    struct timeval pr_utime;		/* User time.  */
+    struct timeval pr_stime;		/* System time.  */
+    struct timeval pr_cutime;		/* Cumulative user time.  */
+    struct timeval pr_cstime;		/* Cumulative system time.  */
+    elf_gregset_t pr_reg;		/* GP registers.  */
+    int pr_fpvalid;			/* True if math copro being used.  */
+  };
+
+
+#define ELF_PRARGSZ     (80)    /* Number of chars for args.  */
+
+struct elf_prpsinfo
+  {
+    char pr_state;			/* Numeric process state.  */
+    char pr_sname;			/* Char for pr_state.  */
+    char pr_zomb;			/* Zombie.  */
+    char pr_nice;			/* Nice val.  */
+    unsigned long int pr_flag;		/* Flags.  */
+    unsigned short int pr_uid;
+    unsigned short int pr_gid;
+    int pr_pid, pr_ppid, pr_pgrp, pr_sid;
+    /* Lots missing */
+    char pr_fname[16];			/* Filename of executable.  */
+    char pr_psargs[ELF_PRARGSZ];	/* Initial part of arg list.  */
+  };
+
+
+/* The rest of this file provides the types for emulation of the
+   Solaris <proc_service.h> interfaces that should be implemented by
+   users of libthread_db.  */
+
+/* Addresses.  */
+typedef void *psaddr_t;
+
+/* Register sets.  Linux has different names.  */
+typedef elf_gregset_t prgregset_t;
+typedef elf_fpregset_t prfpregset_t;
+
+/* We don't have any differences between processes and threads,
+   therefore have only one PID type.  */
+typedef __pid_t lwpid_t;
+
+/* Process status and info.  In the end we do provide typedefs for them.  */
+typedef struct elf_prstatus prstatus_t;
+typedef struct elf_prpsinfo prpsinfo_t;
+
+__END_DECLS
+
+#endif	/* sys/procfs.h */
diff --git a/libc/sysdeps/linux/csky/sys/ucontext.h b/libc/sysdeps/linux/csky/sys/ucontext.h
new file mode 100644
index 0000000..5917688
--- /dev/null
+++ b/libc/sysdeps/linux/csky/sys/ucontext.h
@@ -0,0 +1,17 @@ 
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H	1
+
+#include <features.h>
+#include <signal.h>
+#include <bits/sigcontext.h>
+
+typedef struct ucontext
+{
+	unsigned long int uc_flags;
+	struct ucontext * uc_link;
+	stack_t           uc_stack;
+	struct sigcontext uc_mcontext;
+	sigset_t          uc_sigmask;
+} ucontext_t;
+
+#endif /* sys/ucontext.h */
diff --git a/libc/sysdeps/linux/csky/sys/user.h b/libc/sysdeps/linux/csky/sys/user.h
new file mode 100644
index 0000000..4ab1972
--- /dev/null
+++ b/libc/sysdeps/linux/csky/sys/user.h
@@ -0,0 +1,48 @@ 
+#ifndef _SYS_USER_H
+#define _SYS_USER_H  1
+
+struct user_fpregs {
+	unsigned long  fsr;         /* fpu status reg */
+	unsigned long  fesr;        /* fpu exception status reg */
+	unsigned long  fp[32];      /* fpu general regs */
+};
+
+struct user_regs {
+#if defined(__CSKYABIV2__)
+	unsigned long int uregs[34];  /* CSKY V2 has 32 general rgister */
+#else
+	unsigned long int uregs[18];  /* CSKY V1 has 16 general rgister */
+#endif
+};
+
+/*
+ * When the kernel dumps core, it starts by dumping the user struct -
+ * this will be used by gdb to figure out where the data and stack segments
+ * are within the file, and what virtual addresses to use.
+ */
+struct user{
+/* We start with the registers, to mimic the way that "memory" is returned
+   from the ptrace(3,...) function.  */
+	struct user_regs    regs; /* Where the registers are actually stored */
+	int                 u_fpvalid;  /* True if math co-processor being used. */
+
+/* The rest of this junk is to help gdb figure out what goes where */
+	unsigned long int   u_tsize;	/* Text segment size (pages). */
+	unsigned long int   u_dsize;	/* Data segment size (pages). */
+	unsigned long int   u_ssize;	/* Stack segment size (pages). */
+	unsigned long       start_code; /* Starting virtual address of text. */
+	unsigned long       start_stack;/* Starting virtual address of stack area.
+					   This is actually the bottom of the stack,
+					   the top of the stack is always found in
+					   the esp register.  */
+	long int            signal;     /* Signal that caused the core dump. */
+	int                 reserved;	/* No longer used */
+	struct user_regs *  u_ar0;	/* Used by gdb to help find the values
+					   for the registers. */
+	unsigned long       magic;	/* To uniquely identify a core file */
+	char                u_comm[32];	/* User command that was responsible */
+	struct user_fpregs  u_fp;
+	struct user_fpregs* u_fpstate;	/* Math Co-processor pointer. */
+};
+
+#endif /* _SYS_USER_H */
diff --git a/libc/sysdeps/linux/csky/sysdep.h b/libc/sysdeps/linux/csky/sysdep.h
new file mode 100644
index 0000000..2fcff68
--- /dev/null
+++ b/libc/sysdeps/linux/csky/sysdep.h
@@ -0,0 +1,204 @@ 
+#ifndef _LINUX_CSKY_SYSDEP_H
+#define _LINUX_CSKY_SYSDEP_H 1
+
+#include <common/sysdep.h>
+#include <sys/syscall.h>
+
+#undef	SYS_ify
+#define	SYS_ify(name) (__NR_##name)
+
+#ifdef __ASSEMBLER__
+
+/* ELF uses byte-counts for .align, most others use log2 of count of bytes.  */
+#define ALIGNARG(log2) log2
+/* For ELF we need the `.type' directive to make shared libs work right.  */
+#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,%##typearg;
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
+
+#define	ENTRY(name) \
+  .globl C_SYMBOL_NAME(name); \
+  ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),function) \
+  .align ALIGNARG(4); \
+  C_LABEL(name)
+
+#undef END
+#define END(name) ASM_SIZE_DIRECTIVE(name)
+
+#undef	ret_ERRVAL
+#define	ret_ERRVAL rts
+
+#undef	PSEUDO_END
+#define	PSEUDO_END(name) END(name)
+
+#ifdef __PIC__
+#define __GET_GB \
+  bsr 1f; \
+  1: lrw gb, 1b@GOTPC; \
+  addu gb, lr;
+
+/*
+ * __JSR must be used with __GET_GB and SAVE_ARGS
+ */
+#define __JSR(symbol) \
+  lrw a2, symbol@PLT; \
+  add a2, gb; \
+  ld.w a2, (a2); \
+  jsr a2;
+
+#define PSEUDO_ERRJMP \
+  subi sp, 8; \
+  st.w lr, (sp); \
+  st.w gb, (sp, 4); \
+  __GET_GB \
+  lrw a2, __syscall_error@PLT; \
+  addu a2, gb; \
+  ld.w a2, (a2); \
+  jsr a2; \
+  ld.w lr, (sp); \
+  ld.w gb, (sp, 4); \
+  addi sp, 8; \
+  rts;
+
+#else /* __PIC__ */
+
+#define __GET_GB
+#define __JSR(symbol) jsri symbol;
+#define PSEUDO_ERRJMP \
+  subi	sp, 4; \
+  stw	lr, (sp, 0); \
+  jsri	__syscall_error; \
+  ldw	lr, (sp, 0); \
+  addi	sp, 4; \
+  rts;
+
+#endif /* __PIC__ */
+
+#define PSEUDO_ERRVAL(name, syscall_name, args) \
+  .text; \
+  99: PSEUDO_ERRJMP; \
+  ENTRY(name); \
+  DO_CALL(syscall_name, args); \
+  btsti	a0, 31; \
+  bt 99b;
+
+#undef PSEUDO_END_ERRVAL
+#define PSEUDO_END_ERRVAL(name) \
+  rts; \
+  END(name)
+
+/* DO_CALL */
+#undef	DO_CALL
+#ifdef	__CSKYABIV2__
+
+#define	DO_CALL(syscall_name, args) \
+  DOARGS_##args \
+  mov	t0, r7; \
+  lrw	r7, SYS_ify (syscall_name); \
+  trap	0; \
+  mov	r7, t0; \
+  UNDOARGS_##args
+
+#define DOARGS_0
+#define DOARGS_1
+#define DOARGS_2
+#define DOARGS_3
+#define DOARGS_4
+#define DOARGS_5 subi sp, 4; st.w r4, (sp, 0); ld.w r4, (sp, 4);
+#define DOARGS_6 subi sp, 8; stm r4-r5, (sp); ld.w r4, (sp, 8); ld.w r5, (sp, 12);
+
+#define UNDOARGS_0
+#define UNDOARGS_1
+#define UNDOARGS_2
+#define UNDOARGS_3
+#define UNDOARGS_4
+#define UNDOARGS_5 ld.w r4, (sp, 0); addi sp, 4;
+#define UNDOARGS_6 ldm r4-r5, (sp); addi sp, 8;
+
+#else /* __CSKYABIV2__ */
+
+#define DO_CALL(syscall_name, args) \
+  lrw  r1, SYS_ify (syscall_name); \
+  trap 0;
+
+#define DOARGS_0
+#define DOARGS_1
+#define DOARGS_2
+#define DOARGS_3
+#define DOARGS_4
+#define DOARGS_5
+#define DOARGS_6
+
+#define UNDOARGS_0
+#define UNDOARGS_1
+#define UNDOARGS_2
+#define UNDOARGS_3
+#define UNDOARGS_4
+#define UNDOARGS_5
+#define UNDOARGS_6
+
+#endif /* __CSKYABIV2__ */
+
+/*
+ * define DO_CALL_2, only ABIV2 need DO_CALL_2
+ * to be quite different with DO_CALL, DO_CALL_2 need not save r7.
+ */
+#ifdef __CSKYABIV2__
+#undef  DO_CALL_2
+#define DO_CALL_2(syscall_name, args) \
+  DOARGS2_##args; \
+  lrw	r7, SYS_ify(syscall_name); \
+  trap	0; \
+  UNDOARGS2_##args
+#undef  DOARGS2_0
+#define DOARGS2_0
+
+#undef  DOARGS2_1
+#define DOARGS2_1 DOARGS2_0
+#undef  DOARGS2_2
+#define DOARGS2_2 DOARGS2_0
+#undef  DOARGS2_3
+#define DOARGS2_3 DOARGS2_0
+#undef  DOARGS2_4
+#define DOARGS2_4 DOARGS2_0
+#undef  DOARGS2_5
+#define DOARGS2_5 \
+  subi sp, 8; \
+  cfi_adjust_cfa_offset (8); \
+  stw  r4, (sp, 0); \
+  ldw  r4, (sp, 24)
+#undef  DOARGS2_6
+#define DOARGS2_6 \
+  subi sp, 8; \
+  cfi_adjust_cfa_offset (8); \
+  stw  r4, (sp, 0); \
+  stw  r5, (sp, 4); \
+  ldw  r4, (sp, 24); \
+  ldw  r5, (sp, 28)
+
+#undef  UNDOARGS2_0
+#define UNDOARGS2_0
+
+#undef  UNDOARGS2_1
+#define UNDOARGS2_1 UNDOARGS2_0
+#undef  UNDOARGS2_2
+#define UNDOARGS2_2 UNDOARGS2_0
+#undef  UNDOARGS2_3
+#define UNDOARGS2_3 UNDOARGS2_0
+#undef  UNDOARGS2_4
+#define UNDOARGS2_4 UNDOARGS2_0
+#undef  UNDOARGS2_5
+#define UNDOARGS2_5 \
+  ldw  r4, (sp, 0); \
+  addi sp, 8
+
+#undef  UNDOARGS2_6
+#define UNDOARGS2_6 \
+  ldw  r4, (sp, 0); \
+  ldw  r5, (sp, 4); \
+  addi sp, 8
+
+#endif  /* __CSKYABIV2__ */
+
+#endif /* __ASSEMBLER__ */
+#endif /* _LINUX_CSKY_SYSDEP_H */
+
diff --git a/libc/sysdeps/linux/csky/vfork.S b/libc/sysdeps/linux/csky/vfork.S
new file mode 100644
index 0000000..a28bb32
--- /dev/null
+++ b/libc/sysdeps/linux/csky/vfork.S
@@ -0,0 +1,6 @@ 
+#include <sysdep.h>
+PSEUDO_ERRVAL(__vfork, vfork, 0)
+PSEUDO_END_ERRVAL(__vfork)
+weak_alias(__vfork, vfork)
+libc_hidden_weak(vfork)
+
diff --git a/libpthread/nptl/sysdeps/csky/Makefile b/libpthread/nptl/sysdeps/csky/Makefile
new file mode 100644
index 0000000..43dc60a
--- /dev/null
+++ b/libpthread/nptl/sysdeps/csky/Makefile
@@ -0,0 +1,6 @@ 
+top_srcdir=../../../../
+top_builddir=../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules
diff --git a/libpthread/nptl/sysdeps/csky/Makefile.arch b/libpthread/nptl/sysdeps/csky/Makefile.arch
new file mode 100644
index 0000000..0e0a5e6
--- /dev/null
+++ b/libpthread/nptl/sysdeps/csky/Makefile.arch
@@ -0,0 +1,7 @@ 
+CFLAGS-pt-raise.c = -DNOT_IN_libc -DIS_IN_libpthread
+
+ASFLAGS-pthread_spin_lock.S = -DNOT_IN_libc -DIS_IN_libpthread
+ASFLAGS-pthread_spin_trylock.S = -DNOT_IN_libc -DIS_IN_libpthread
+
+libc_arch_a_CSRC = libc-tls.c
+
diff --git a/libpthread/nptl/sysdeps/csky/dl-tls.h b/libpthread/nptl/sysdeps/csky/dl-tls.h
new file mode 100644
index 0000000..70f7e96
--- /dev/null
+++ b/libpthread/nptl/sysdeps/csky/dl-tls.h
@@ -0,0 +1,9 @@ 
+/* Type used for the representation of TLS information in the GOT.  */
+typedef struct
+{
+	unsigned long int ti_module;
+	unsigned long int ti_offset;
+} tls_index;
+
+extern void *__tls_get_addr (tls_index *ti);
+
diff --git a/libpthread/nptl/sysdeps/csky/libc-tls.c b/libpthread/nptl/sysdeps/csky/libc-tls.c
new file mode 100644
index 0000000..ceb61f8
--- /dev/null
+++ b/libpthread/nptl/sysdeps/csky/libc-tls.c
@@ -0,0 +1,18 @@ 
+#include <sysdeps/generic/libc-tls.c>
+#include <dl-tls.h>
+
+#if defined(USE_TLS) && USE_TLS
+
+/* On CSKY, linker optimizations are not required, so __tls_get_addr
+   can be called even in statically linked binaries.  In this case module
+   must be always 1 and PT_TLS segment exist in the binary, otherwise it
+   would not link.  */
+
+void *
+__tls_get_addr (tls_index *ti)
+{
+	dtv_t *dtv = THREAD_DTV ();
+	return (char *) dtv[1].pointer.val + ti->ti_offset;
+}
+
+#endif
diff --git a/libpthread/nptl/sysdeps/csky/pthread_spin_lock.S b/libpthread/nptl/sysdeps/csky/pthread_spin_lock.S
new file mode 100644
index 0000000..da6e234
--- /dev/null
+++ b/libpthread/nptl/sysdeps/csky/pthread_spin_lock.S
@@ -0,0 +1,18 @@ 
+#include <sysdep.h>
+
+	.text
+	.align	4
+
+ENTRY (pthread_spin_lock)
+	mov	a2, a0
+1:
+	movi	a0, 0
+	movi	a1, 1
+	trap	2		// trap 2 use to cmpxchg
+	cmpnei	a0, 0
+	bt	1b
+	movi	a0, 0
+	jmp	r15
+
+    /* TODO */
+END (pthread_spin_lock)
diff --git a/libpthread/nptl/sysdeps/csky/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/csky/pthread_spin_trylock.S
new file mode 100644
index 0000000..113e94d
--- /dev/null
+++ b/libpthread/nptl/sysdeps/csky/pthread_spin_trylock.S
@@ -0,0 +1,16 @@ 
+#define _ERRNO_H 1
+#include <bits/errno.h>
+#include <sysdep.h>
+
+.text
+ENTRY (pthread_spin_trylock)
+	mov	a2, a0
+	movi	a0, 0
+	movi	a1, 1
+	trap	2		// trap 2 use to cmpxchg
+	cmpnei	a0, 0
+	bf	1f
+	movi	a0, EBUSY
+1:
+	jmp	r15
+END (pthread_spin_trylock)
diff --git a/libpthread/nptl/sysdeps/csky/pthreaddef.h b/libpthread/nptl/sysdeps/csky/pthreaddef.h
new file mode 100644
index 0000000..da6a0fa
--- /dev/null
+++ b/libpthread/nptl/sysdeps/csky/pthreaddef.h
@@ -0,0 +1,19 @@ 
+/* Default stack size.  */
+#define ARCH_STACK_DEFAULT_SIZE	(2 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning.  SSE requires 16
+   bytes.  */
+#define STACK_ALIGN		16
+
+/* Minimal stack size after allocating thread descriptor and guard size.  */
+#define MINIMAL_REST_STACK	2048
+
+/* Alignment requirement for TCB.  */
+#define TCB_ALIGNMENT		16
+
+/* Location of current stack frame.  */
+#define CURRENT_STACK_FRAME	__builtin_frame_address (0)
+
+/* XXX Until we have a better place keep the definitions here.  */
+#define __exit_thread_inline(val) \
+  INLINE_SYSCALL (exit, 1, (val))
diff --git a/libpthread/nptl/sysdeps/csky/tcb-offsets.sym b/libpthread/nptl/sysdeps/csky/tcb-offsets.sym
new file mode 100644
index 0000000..bf9c0a1
--- /dev/null
+++ b/libpthread/nptl/sysdeps/csky/tcb-offsets.sym
@@ -0,0 +1,10 @@ 
+#include <sysdep.h>
+#include <tls.h>
+
+--
+
+-- Derive offsets relative to the thread register.
+#define thread_offsetof(mem)	(long)(offsetof(struct pthread, mem) - sizeof(struct pthread))
+
+MULTIPLE_THREADS_OFFSET		thread_offsetof (header.multiple_threads)
+TID_OFFSET			thread_offsetof (tid)
diff --git a/libpthread/nptl/sysdeps/csky/tls.h b/libpthread/nptl/sysdeps/csky/tls.h
new file mode 100644
index 0000000..721551c
--- /dev/null
+++ b/libpthread/nptl/sysdeps/csky/tls.h
@@ -0,0 +1,170 @@ 
+#ifndef _TLS_H
+#define _TLS_H 1
+
+#ifndef __ASSEMBLER__
+
+# include <stdbool.h>
+# include <stddef.h>
+# include <stdint.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
+} dtv_t;
+
+#ifdef __CSKYABIV2__
+/* define r31 as thread pointer register? */
+# define READ_THREAD_POINTER() \
+    ({ void *__result;                                \
+       __asm__ __volatile__ ("mov %0, r31"	          \
+                             : "=r" (__result));      \
+       __result; })
+#else
+# define READ_THREAD_POINTER() \
+    ({ register unsigned int __result __asm__("a0");                 \
+       __asm__ __volatile__ ("trap 3;"	    \
+                             : "=r" (__result) : : );      \
+       __result; })
+#endif
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+# ifdef __CSKYABIV2__
+/* define r31 as thread pointer register? */
+# define READ_THREAD_POINTER() \
+       mov r0, r31;
+# else
+# define READ_THREAD_POINTER() \
+       trap 3;
+# endif
+#endif /* __ASSEMBLER__ */
+
+/* We require TLS support in the tools.  */
+#define HAVE_TLS_SUPPORT                1
+#define HAVE_TLS_MODEL_ATTRIBUTE        1
+#define HAVE___THREAD                   1
+
+/* Signal that TLS support is available.  */
+#define USE_TLS	1
+
+# ifndef __ASSEMBLER__
+
+/* Get system call information.  */
+#  include <sysdep.h>
+
+/* The TP points to the start of the thread blocks.  */
+# define TLS_DTV_AT_TP	1
+
+/* Get the thread descriptor definition.  */
+# include <../../descr.h>
+
+typedef struct
+{
+  dtv_t *dtv;
+  void *private;
+} tcbhead_t;
+
+/* This is the size of the initial TCB.  */
+#  define TLS_INIT_TCB_SIZE	     sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB.  */
+#  define TLS_INIT_TCB_ALIGN     16
+
+/* This is the size of the TCB.  */
+#  define TLS_TCB_SIZE		sizeof (tcbhead_t)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN	    16
+
+/* This is the size we need before TCB.  */
+#  define TLS_PRE_TCB_SIZE	sizeof (struct pthread)
+
+/* The thread pointer (in hardware register $29) points to the end of
+   the TCB + 0x7000, as for PowerPC.  The pthread_descr structure is
+   immediately in front of the TCB.  */
+# define TLS_TCB_OFFSET     0//0x7000
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+#  define INSTALL_DTV(tcbp, dtvp) \
+  (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1)
+
+/* Install new dtv for current thread.  */
+#  define INSTALL_NEW_DTV(dtv) \
+  (THREAD_DTV() = (dtv))
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(tcbp) \
+  (((tcbhead_t *) (tcbp))->dtv)
+
+/* Code to initially initialize the thread pointer.  This might need
+   special attention since 'errno' is not yet available and if the
+   operation can cause a failure 'errno' must not be touched.  */
+# define TLS_INIT_TP(tcbp, secondcall) \
+  ({ INTERNAL_SYSCALL_DECL (err);                   \
+     long result_var;                           \
+     result_var = INTERNAL_SYSCALL (set_thread_area, err, 1,        \
+                    (char *) (tcbp) + TLS_TCB_OFFSET);  \
+     INTERNAL_SYSCALL_ERROR_P (result_var, err)             \
+       ? "unknown error" : NULL; })
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))->dtv)
+
+/* Return the thread descriptor for the current thread.  */
+#  undef THREAD_SELF
+#  define THREAD_SELF \
+ ((struct pthread *) (READ_THREAD_POINTER ()                 \
+              - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE))
+
+/* Magic for libthread_db to know how to do THREAD_SELF.  */
+# define DB_THREAD_SELF \
+  CONST_THREAD_AREA (32, sizeof (struct pthread))
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  descr->member
+#define THREAD_GETMEM_NC(descr, member, idx) \
+  descr->member[idx]
+#define THREAD_SETMEM(descr, member, value) \
+  descr->member = (value)
+#define THREAD_SETMEM_NC(descr, member, idx, value) \
+  descr->member[idx] = (value)
+
+/* Initializing the thread pointer will generate a SIGILL if the syscall
+   is not available.  */
+#define TLS_INIT_TP_EXPENSIVE 1
+
+/* Get and set the global scope generation counter in struct pthread.  */
+#define THREAD_GSCOPE_FLAG_UNUSED 0
+#define THREAD_GSCOPE_FLAG_USED   1
+#define THREAD_GSCOPE_FLAG_WAIT   2
+#define THREAD_GSCOPE_RESET_FLAG() \
+  do									     \
+    { int __res								     \
+	= atomic_exchange_rel (&THREAD_SELF->header.gscope_flag,	     \
+			       THREAD_GSCOPE_FLAG_UNUSED);		     \
+      if (__res == THREAD_GSCOPE_FLAG_WAIT)				     \
+	lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE);   \
+    }									     \
+  while (0)
+#define THREAD_GSCOPE_SET_FLAG() \
+  do									     \
+    {									     \
+      THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED;	     \
+      atomic_write_barrier ();						     \
+    }									     \
+  while (0)
+#define THREAD_GSCOPE_WAIT() \
+  GL(dl_wait_lookup_done) ()
+
+#endif /* __ASSEMBLER__ */
+
+#endif	/* tls.h */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/csky/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/Makefile
new file mode 100644
index 0000000..8679a84
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/Makefile
@@ -0,0 +1,6 @@ 
+top_srcdir=../../../../../../../
+top_builddir=../../../../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/csky/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/Makefile.arch
new file mode 100644
index 0000000..6c85eda
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/Makefile.arch
@@ -0,0 +1,4 @@ 
+libpthread_linux_arch_SSRC =
+libpthread_linux_arch_CSRC = pthread_once.c
+
+libc_linux_arch_CSRC = fork.c
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/csky/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/bits/pthreadtypes.h
new file mode 100644
index 0000000..e1b115c
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/bits/pthreadtypes.h
@@ -0,0 +1,181 @@ 
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _BITS_PTHREADTYPES_H
+#define _BITS_PTHREADTYPES_H	1
+
+#include <endian.h>
+
+#define __SIZEOF_PTHREAD_ATTR_T 36
+#define __SIZEOF_PTHREAD_MUTEX_T 24
+#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+#define __SIZEOF_PTHREAD_COND_T 48
+#define __SIZEOF_PTHREAD_COND_COMPAT_T 12
+#define __SIZEOF_PTHREAD_CONDATTR_T 4
+#define __SIZEOF_PTHREAD_RWLOCK_T 32
+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+#define __SIZEOF_PTHREAD_BARRIER_T 20
+#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+
+
+/* Thread identifiers.  The structure of the attribute type is not
+   exposed on purpose.  */
+typedef unsigned long int pthread_t;
+
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_ATTR_T];
+  long int __align;
+} pthread_attr_t;
+
+
+typedef struct __pthread_internal_slist
+{
+  struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+
+
+/* Data structures for mutex handling.  The structure of the attribute
+   type is not exposed on purpose.  */
+typedef union
+{
+  struct __pthread_mutex_s
+  {
+    int __lock;
+    unsigned int __count;
+    int __owner;
+    /* KIND must stay at this position in the structure to maintain
+       binary compatibility.  */
+    int __kind;
+    unsigned int __nusers;
+    __extension__ union
+    {
+      int __spins;
+      __pthread_slist_t __list;
+    };
+  } __data;
+  char __size[__SIZEOF_PTHREAD_MUTEX_T];
+  long int __align;
+} pthread_mutex_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
+  long int __align;
+} pthread_mutexattr_t;
+
+
+/* Data structure for conditional variable handling.  The structure of
+   the attribute type is not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __futex;
+    __extension__ unsigned long long int __total_seq;
+    __extension__ unsigned long long int __wakeup_seq;
+    __extension__ unsigned long long int __woken_seq;
+    void *__mutex;
+    unsigned int __nwaiters;
+    unsigned int __broadcast_seq;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_COND_T];
+  __extension__ long long int __align;
+} pthread_cond_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_CONDATTR_T];
+  long int __align;
+} pthread_condattr_t;
+
+
+/* Keys for thread-specific data */
+typedef unsigned int pthread_key_t;
+
+
+/* Once-only execution */
+typedef int pthread_once_t;
+
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+/* Data structure for read-write lock variable handling.  The
+   structure of the attribute type is not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __nr_readers;
+    unsigned int __readers_wakeup;
+    unsigned int __writer_wakeup;
+    unsigned int __nr_readers_queued;
+    unsigned int __nr_writers_queued;
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned char __pad1;
+    unsigned char __pad2;
+    unsigned char __shared;
+    /* FLAGS must stay at this position in the structure to maintain
+       binary compatibility.  */
+    unsigned char __flags;
+#else
+    /* FLAGS must stay at this position in the structure to maintain
+       binary compatibility.  */
+    unsigned char __flags;
+    unsigned char __shared;
+    unsigned char __pad1;
+    unsigned char __pad2;
+#endif
+    int __writer;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_RWLOCK_T];
+  long int __align;
+} pthread_rwlock_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
+  long int __align;
+} pthread_rwlockattr_t;
+#endif
+
+
+#ifdef __USE_XOPEN2K
+/* POSIX spinlock data type.  */
+typedef volatile int pthread_spinlock_t;
+
+
+/* POSIX barriers data type.  The structure of the type is
+   deliberately not exposed.  */
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_BARRIER_T];
+  long int __align;
+} pthread_barrier_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
+  int __align;
+} pthread_barrierattr_t;
+#endif
+
+
+#endif	/* bits/pthreadtypes.h */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/csky/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/bits/semaphore.h
new file mode 100644
index 0000000..dadfac2
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/bits/semaphore.h
@@ -0,0 +1,35 @@ 
+/* Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _SEMAPHORE_H
+# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
+#endif
+
+
+#define __SIZEOF_SEM_T	16
+
+
+/* Value returned if `sem_open' failed.  */
+#define SEM_FAILED      ((sem_t *) 0)
+
+
+typedef union
+{
+  char __size[__SIZEOF_SEM_T];
+  long int __align;
+} sem_t;
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/csky/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/createthread.c
new file mode 100644
index 0000000..bad8b05
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/createthread.c
@@ -0,0 +1,5 @@ 
+/* Value passed to 'clone' for initialization of the thread register.  */
+#define TLS_VALUE (pd + 1)
+
+/* Get the real implementation.	 */
+#include <sysdeps/pthread/createthread.c>
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/csky/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/fork.c
new file mode 100644
index 0000000..41776f9
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/fork.c
@@ -0,0 +1,31 @@ 
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Phil Blundell <pb@nexus.co.uk>, 2005
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sched.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <tls.h>
+
+
+#define ARCH_FORK()							\
+  INLINE_SYSCALL (clone, 5,						\
+		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,	\
+		  NULL, NULL, &THREAD_SELF->tid, NULL)
+
+#include "../fork.c"
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/csky/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/lowlevellock.h
new file mode 100644
index 0000000..0a56503
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/lowlevellock.h
@@ -0,0 +1,281 @@ 
+/* Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _LOWLEVELLOCK_H
+#define _LOWLEVELLOCK_H	1
+
+#include <time.h>
+#include <sys/param.h>
+#include <bits/pthreadtypes.h>
+#include <atomic.h>
+#include <sysdep.h>
+#include <bits/kernel-features.h>
+
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+#define FUTEX_REQUEUE		3
+#define FUTEX_CMP_REQUEUE	4
+#define FUTEX_WAKE_OP		5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE	((4 << 24) | 1)
+#define FUTEX_LOCK_PI		6
+#define FUTEX_UNLOCK_PI		7
+#define FUTEX_TRYLOCK_PI	8
+#define FUTEX_WAIT_BITSET	9
+#define FUTEX_WAKE_BITSET	10
+#define FUTEX_PRIVATE_FLAG	128
+#define FUTEX_CLOCK_REALTIME	256
+
+#define FUTEX_BITSET_MATCH_ANY	0xffffffff
+
+/* Values for 'private' parameter of locking macros.  Yes, the
+   definition seems to be backwards.  But it is not.  The bit will be
+   reversed before passing to the system call.  */
+#define LLL_PRIVATE	0
+#define LLL_SHARED	FUTEX_PRIVATE_FLAG
+
+
+#if !defined NOT_IN_libc || defined IS_IN_rtld
+/* In libc.so or ld.so all futexes are private.  */
+# ifdef __ASSUME_PRIVATE_FUTEX
+#  define __lll_private_flag(fl, private) \
+  ((fl) | FUTEX_PRIVATE_FLAG)
+# else
+#  define __lll_private_flag(fl, private) \
+  ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
+# endif
+#else
+# ifdef __ASSUME_PRIVATE_FUTEX
+#  define __lll_private_flag(fl, private) \
+  (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
+# else
+#  define __lll_private_flag(fl, private) \
+  (__builtin_constant_p (private)					      \
+   ? ((private) == 0							      \
+      ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))	      \
+      : (fl))								      \
+   : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG)				      \
+	      & THREAD_GETMEM (THREAD_SELF, header.private_futex))))
+# endif
+#endif
+
+#define lll_futex_wait(futexp, val, private) \
+  lll_futex_timed_wait(futexp, val, NULL, private)
+
+#define lll_futex_timed_wait(futexp, val, timespec, private) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),		      \
+			      __lll_private_flag (FUTEX_WAIT, private),	      \
+			      (val), (timespec));			      \
+    __ret;								      \
+  })
+
+#define lll_futex_wake(futexp, nr, private) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),		      \
+			      __lll_private_flag (FUTEX_WAKE, private),	      \
+			      (nr), 0);					      \
+    __ret;								      \
+  })
+
+#define lll_robust_dead(futexv, private) \
+  do									      \
+    {									      \
+      int *__futexp = &(futexv);					      \
+      atomic_or (__futexp, FUTEX_OWNER_DIED);				      \
+      lll_futex_wake (__futexp, 1, private);				      \
+    }									      \
+  while (0)
+
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		      \
+			      __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
+			      (nr_wake), (nr_move), (mutex), (val));	      \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
+  })
+
+
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),		      \
+			      __lll_private_flag (FUTEX_WAKE_OP, private),    \
+			      (nr_wake), (nr_wake2), (futexp2),		      \
+			      FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);		      \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \
+  })
+
+
+#define lll_trylock(lock)	\
+  atomic_compare_and_exchange_val_acq(&(lock), 1, 0)
+
+#define lll_cond_trylock(lock)	\
+  atomic_compare_and_exchange_val_acq(&(lock), 2, 0)
+
+#define __lll_robust_trylock(futex, id) \
+  (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0)
+#define lll_robust_trylock(lock, id) \
+  __lll_robust_trylock (&(lock), id)
+
+extern void __lll_lock_wait_private (int *futex) attribute_hidden;
+extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
+extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
+
+#define __lll_lock(futex, private)					      \
+  ((void) ({								      \
+    int *__futex = (futex);						      \
+    if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex,       \
+								1, 0), 0))    \
+      {									      \
+	if (__builtin_constant_p (private) && (private) == LLL_PRIVATE)	      \
+	  __lll_lock_wait_private (__futex);				      \
+	else								      \
+	  __lll_lock_wait (__futex, private);				      \
+      }									      \
+  }))
+#define lll_lock(futex, private) __lll_lock (&(futex), private)
+
+
+#define __lll_robust_lock(futex, id, private)				      \
+  ({									      \
+    int *__futex = (futex);						      \
+    int __val = 0;							      \
+									      \
+    if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
+								0), 0))	      \
+      __val = __lll_robust_lock_wait (__futex, private);		      \
+    __val;								      \
+  })
+#define lll_robust_lock(futex, id, private) \
+  __lll_robust_lock (&(futex), id, private)
+
+
+#define __lll_cond_lock(futex, private)					      \
+  ((void) ({								      \
+    int *__futex = (futex);						      \
+    if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0))		      \
+      __lll_lock_wait (__futex, private);				      \
+  }))
+#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
+
+
+#define lll_robust_cond_lock(futex, id, private) \
+  __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
+
+
+extern int __lll_timedlock_wait (int *futex, const struct timespec *,
+				 int private) attribute_hidden;
+extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
+					int private) attribute_hidden;
+
+#define __lll_timedlock(futex, abstime, private)			      \
+  ({									      \
+     int *__futex = (futex);						      \
+     int __val = 0;							      \
+									      \
+     if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0))	      \
+       __val = __lll_timedlock_wait (__futex, abstime, private);	      \
+     __val;								      \
+  })
+#define lll_timedlock(futex, abstime, private) \
+  __lll_timedlock (&(futex), abstime, private)
+
+
+#define __lll_robust_timedlock(futex, abstime, id, private)		      \
+  ({									      \
+    int *__futex = (futex);						      \
+    int __val = 0;							      \
+									      \
+    if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
+								0), 0))	      \
+      __val = __lll_robust_timedlock_wait (__futex, abstime, private);	      \
+    __val;								      \
+  })
+#define lll_robust_timedlock(futex, abstime, id, private) \
+  __lll_robust_timedlock (&(futex), abstime, id, private)
+
+
+#define __lll_unlock(futex, private) \
+  (void)							\
+    ({ int *__futex = (futex);					\
+       int __oldval = atomic_exchange_rel (__futex, 0);		\
+       if (__builtin_expect (__oldval > 1, 0))			\
+	 lll_futex_wake (__futex, 1, private);			\
+    })
+#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
+
+
+#define __lll_robust_unlock(futex, private) \
+  (void)							\
+    ({ int *__futex = (futex);					\
+       int __oldval = atomic_exchange_rel (__futex, 0);		\
+       if (__builtin_expect (__oldval & FUTEX_WAITERS, 0))	\
+	 lll_futex_wake (__futex, 1, private);			\
+    })
+#define lll_robust_unlock(futex, private) \
+  __lll_robust_unlock(&(futex), private)
+
+
+#define lll_islocked(futex) \
+  (futex != 0)
+
+
+/* Our internal lock implementation is identical to the binary-compatible
+   mutex implementation. */
+
+/* Initializers for lock.  */
+#define LLL_LOCK_INITIALIZER		(0)
+#define LLL_LOCK_INITIALIZER_LOCKED	(1)
+
+/* The states of a lock are:
+    0  -  untaken
+    1  -  taken by one user
+   >1  -  taken by more users */
+
+/* The kernel notifies a process which uses CLONE_CLEARTID via futex
+   wakeup when the clone terminates.  The memory location contains the
+   thread ID while the clone is running and is reset to zero
+   afterwards.	*/
+#define lll_wait_tid(tid) \
+  do {					\
+    __typeof (tid) __tid;		\
+    while ((__tid = (tid)) != 0)	\
+      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+  } while (0)
+
+extern int __lll_timedwait_tid (int *, const struct timespec *)
+     attribute_hidden;
+
+#define lll_timedwait_tid(tid, abstime) \
+  ({							\
+    int __res = 0;					\
+    if ((tid) != 0)					\
+      __res = __lll_timedwait_tid (&(tid), (abstime));	\
+    __res;						\
+  })
+
+#endif	/* lowlevellock.h */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/csky/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/pthread_once.c
new file mode 100644
index 0000000..e977a7d
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/pthread_once.c
@@ -0,0 +1,100 @@ 
+/* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include "pthreadP.h"
+#include <lowlevellock.h>
+
+unsigned long int __fork_generation attribute_hidden;
+
+static void
+clear_once_control (void *arg)
+{
+  pthread_once_t *once_control = (pthread_once_t *) arg;
+
+  *once_control = 0;
+  lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
+}
+
+int
+attribute_protected
+__pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
+{
+  for (;;)
+    {
+      int oldval;
+      int newval;
+
+      /* Pseudo code:
+	 newval = __fork_generation | 1;
+	 oldval = *once_control;
+	 if ((oldval & 2) == 0)
+	   *once_control = newval;
+	 Do this atomically.
+      */
+      do
+	{
+	  newval = __fork_generation | 1;
+	  oldval = *once_control;
+	  if (oldval & 2)
+	    break;
+	} while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval);
+
+      /* Check if the initializer has already been done.  */
+      if ((oldval & 2) != 0)
+	return 0;
+
+      /* Check if another thread already runs the initializer.	*/
+      if ((oldval & 1) == 0)
+	break;
+
+      /* Check whether the initializer execution was interrupted by a fork.  */
+      if (oldval != newval)
+	break;
+
+      /* Same generation, some other thread was faster. Wait.  */
+      lll_futex_wait (once_control, oldval, LLL_PRIVATE);
+    }
+
+  /* This thread is the first here.  Do the initialization.
+     Register a cleanup handler so that in case the thread gets
+     interrupted the initialization can be restarted.  */
+  pthread_cleanup_push (clear_once_control, once_control);
+
+  init_routine ();
+
+  pthread_cleanup_pop (0);
+
+  /* Say that the initialisation is done.  */
+  *once_control = __fork_generation | 2;
+
+  /* Wake up all other threads.  */
+  lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
+
+  return 0;
+}
+weak_alias (__pthread_once, pthread_once)
+strong_alias (__pthread_once, __pthread_once_internal)
+
+#if defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__PIC__)
+/* When statically linked, if pthread_create is used, this file
+   will be brought in.  The exception handling code in GCC assumes
+   that if pthread_create is available, so are these.  */
+const void *include_pthread_getspecific attribute_hidden = pthread_getspecific;
+const void *include_pthread_setspecific attribute_hidden = pthread_setspecific;
+const void *include_pthread_key_create attribute_hidden = pthread_key_create;
+#endif
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/csky/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/sysdep-cancel.h
new file mode 100644
index 0000000..34c43b0
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/csky/sysdep-cancel.h
@@ -0,0 +1,33 @@ 
+#include <sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+#include <pthreadP.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# ifdef IS_IN_libpthread
+#  define __local_multiple_threads __pthread_multiple_threads
+# elif !defined NOT_IN_libc
+#  define __local_multiple_threads __libc_multiple_threads
+# endif
+
+# if defined IS_IN_libpthread || !defined NOT_IN_libc
+extern int __local_multiple_threads attribute_hidden;
+#  define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+# else
+#  define SINGLE_THREAD_P						\
+   __builtin_expect (THREAD_GETMEM (THREAD_SELF,			\
+				    header.multiple_threads) == 0, 1)
+# endif
+
+#else
+
+# define SINGLE_THREAD_P 1
+# define NO_CANCELLATION 1
+
+#endif
+
+#define RTLD_SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+				   header.multiple_threads) == 0, 1)