devel
Threads by month
- ----- 2025 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- 1171 discussions
I ran into a build failure on xfsprogs-4.13.1 under uclibc-ng-1.0.26 due to it
not finding the 'f_flags' member in 'struct statfs'. Glibc has this member,
but not uclibc-ng. Is this something going away, something yet to be added, or
something controlled by a CONFIG_* directive?
This is a diff of /usr/include/bits/statfs.h from a glibc root (a/) and a
uclibc-ng root (b/):
--- a/usr/include/bits/statfs.h 2017-10-14 18:15:40.672366000 -0400
+++ b/usr/include/bits/statfs.h 2017-11-01 13:34:08.335874000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 2000 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
@@ -12,7 +12,7 @@
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, see
+ License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _SYS_STATFS_H
@@ -44,8 +44,7 @@ struct statfs
/* Linux specials */
__fsid_t f_fsid;
long int f_namelen;
- long int f_flags;
- long int f_spare[5];
+ long int f_spare[6];
};
#ifdef __USE_LARGEFILE64
@@ -64,8 +63,7 @@ struct statfs64
/* Linux specials */
__fsid_t f_fsid;
long int f_namelen;
- long int f_flags;
- long int f_spare[5];
+ long int f_spare[6];
};
#endif
--
Joshua Kinard
Gentoo/MIPS
kumba(a)gentoo.org
6144R/F5C6C943 2015-04-27
177C 1972 1FB8 F254 BAD0 3E72 5C63 F4E3 F5C6 C943
"The past tempts us, the present confuses us, the future frightens us. And our
lives slip away, moment by moment, lost in that vast, terrible in-between."
--Emperor Turhan, Centauri Republic
2
2
Hi,
I released uClibc-ng 1.0.27 yesterday.
It adds support for c-sky architecture.
Many thanks to Guo Ren!
Furthermore it contains a lot of or1k NPTL bugfixes,
which reduces the seen test failures running the uClibc-ng
testsuite inside Qemu a lot.
Many thanks to Stafford Horne!
And a lot of other bugfixes.
Thanks to the many new contributors!
best regards
Waldemar
1
0
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(a)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
diff --git a/MAINTAINERS b/MAINTAINERS
index 642f903..d5aa024 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7,6 +7,9 @@ ARC:
Alexey Brodkin <Alexey.Brodkin(a)synopsys.com>
Vineet Gupta <Vineet.Gupta1(a)synopsys.com>
+CSKY:
+Guo Ren <ren_guo(a)c-sky.com>
+
MIPS:
Matthew Fortune <Matthew.Fortune(a)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(a)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(a)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)
--
2.7.4
2
6
Signed-off-by: Guo Ren <ren_guo(a)c-sky.com>
---
utils/ldd.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/utils/ldd.c b/utils/ldd.c
index 963dd1a..4c5635c 100644
--- a/utils/ldd.c
+++ b/utils/ldd.c
@@ -54,6 +54,11 @@
#define ELFCLASSM ELFCLASS32
#endif
+#if defined(__csky__)
+#define MATCH_MACHINE(x) (x == EM_MCORE)
+#define ELFCLASSM ELFCLASS32
+#endif
+
#if defined(__frv__)
#define MATCH_MACHINE(x) (x == EM_CYGNUS_FRV)
#define ELFCLASSM ELFCLASS32
--
2.7.4
2
1

Re: [uclibc-ng-devel] [PATCH] malloc-standard/malloc.h: use getpagesize
by Waldemar Brodkorb 03 Nov '17
by Waldemar Brodkorb 03 Nov '17
03 Nov '17
Hi,
איתי שוורץ wrote,
> sure,
>
> The following program compiled using gcc-7.2 binutils-2-29.1 uclibc-ng (newest
> from git):
> user@yitai:~/test$ cat test.c
> #include <stdlib.h>
> #include <stdio.h>
> #include <unistd.h>
>
> int main(void) {
> return 0;
> }
>
> with the patch:
>
> user@yitai:~/test$ make
> x86_64-unknown-linux-uclibc-gcc test.c -o test -static
> wc -c test
> 45248 test
>
> without the patch:
>
> user@yitai:~/test$ make
> x86_64-unknown-linux-uclibc-gcc test.c -o test -static
> wc -c test
> 52592 test
>
> As you can see, The patch save 7344 bytes (about %14 precent smaller) for
> x86_64.
Thanks, applied and pushed,
best regards
Waldemar
1
0
Hi,
I've upgraded Optware-ng uClibc-ng from 1.0.15 to 1.0.26 a while ago. It
called for recompilation of most of the packages, but this issue seems to
be resolved now. The issue I'd like to report is that when the linker
(ld-uClibc.so.0) is built, UCLIBC_RUNTIME_PREFIX seems to evaluate to "/",
even though RUNTIME_PREFIX is set to "/opt" (see attached config). I had to
resort to patching uClibc-ng sources (
https://github.com/Optware/Optware-ng/blob/master/sources/buildroot-armeabi…,
%OPTWARE_TARGET_PREFIX% is replaced with "/opt") to get this fixed. It
wasn't so with 1.0.15, setting RUNTIME_PREFIX to "/opt" made linker look
for libs only in "/opt/lib", "/opt/usr/lib", etc., and not in "/lib" and
such. Is this change intended, or is it a bug?
Thanks,
Alex
P.S. Another thing I noticed that you may want to know. Looking
at ldso/ldso/dl-elf.c, this line seems to be wrong:
> UCLIBC_RUNTIME_PREFIX "usr" LDSO_MULTILIB_DIR,
since LDSO_MULTILIB_DIR defaults to "lib" -- not "/lib", so I'm guessing
you want it this way:
> UCLIBC_RUNTIME_PREFIX "usr/" LDSO_MULTILIB_DIR,
2
3

Re: [uclibc-ng-devel] [PATCH] malloc-standard/malloc.h: use getpagesize
by Waldemar Brodkorb 28 Oct '17
by Waldemar Brodkorb 28 Oct '17
28 Oct '17
Hi,
Yitai Schwartz wrote,
> sysconf creates a lot of code dependencies.
> getpagesize dosen't.
> staticly linked code that calls malloc is now much smaller.
Thanks for the patch. Can you show us some results of the
savings?
best regards
Waldemar
1
0
warning: unused variable 'self' [-Wunused-variable]
Signed-off-by: Guo Ren <ren_guo(a)c-sky.com>
---
libpthread/nptl/sysdeps/unix/sysv/linux/fork.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c
index 8b4b036..9b96152 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c
@@ -144,9 +144,7 @@ fork (void)
if (pid == 0)
{
- struct pthread *self = THREAD_SELF;
-
- assert (THREAD_GETMEM (self, tid) != ppid);
+ assert (THREAD_GETMEM (THREAD_SELF, tid) != ppid);
if (__fork_generation_pointer != NULL)
*__fork_generation_pointer += 4;
--
2.7.4
2
1
Hi, Waldemar
> @Guo: Do you think this is the right patch?
It's OK, and we should put the "elif __NR_socketcall" to every
socketcall syscall implementation.
> What happens if an application tries to use recvmmsg running on an
> older Kernel, will it crash or just do nothing?
>
Kernel will return -EINVAL, no crash.
best regards
Guo Ren
1
0
The recvmmsg and sendmmsg is very important for UDP stream application.
If we only use recvmsg for UDP stream, it will only copy one mtu size
of data in a syscall. And recvmmsg copy as many as you want in a syscall.
So recvmmsg is more efficient,and some applications will depends on the
recvmmsg and sendmmsg, eg: UDP media stream player.
Signed-off-by: Guo Ren <ren_guo(a)c-sky.com>
---
include/sys/socket.h | 30 ++++++++++++++++++++++++++++
libc/inet/Makefile.in | 3 ++-
libc/inet/recvmmsg.c | 8 ++++++++
libc/inet/sendmmsg.c | 8 ++++++++
libc/inet/socketcalls.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
libpthread/nptl/Makefile.in | 2 ++
6 files changed, 98 insertions(+), 1 deletion(-)
create mode 100644 libc/inet/recvmmsg.c
create mode 100644 libc/inet/sendmmsg.c
diff --git a/include/sys/socket.h b/include/sys/socket.h
index 8642312..63dc4b9 100644
--- a/include/sys/socket.h
+++ b/include/sys/socket.h
@@ -97,6 +97,15 @@ typedef union { __SOCKADDR_ALLTYPES
# undef __SOCKADDR_ONETYPE
#endif
+#ifdef __USE_GNU
+/* For `recvmmsg' and `sendmmsg'. */
+struct mmsghdr
+ {
+ struct msghdr msg_hdr; /* Actual message header. */
+ unsigned int msg_len; /* Number of received or sent bytes for the
+ entry. */
+ };
+#endif
/* Create a new socket of type TYPE in domain DOMAIN, using
protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically.
@@ -190,6 +199,17 @@ extern ssize_t sendmsg (int __fd, const struct msghdr *__message,
int __flags);
libc_hidden_proto(sendmsg)
+#ifdef __USE_GNU
+/* Send a VLEN messages as described by VMESSAGES to socket FD.
+ Returns the number of datagrams successfully written or -1 for errors.
+
+ This function is a cancellation point and therefore not marked with
+ __THROW. */
+extern ssize_t sendmmsg (int __fd, struct mmsghdr *__vmessages,
+ size_t __vlen, int __flags);
+libc_hidden_proto(sendmmsg)
+#endif
+
/* Receive a message as described by MESSAGE from socket FD.
Returns the number of bytes read or -1 for errors.
@@ -198,6 +218,16 @@ libc_hidden_proto(sendmsg)
extern ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags);
libc_hidden_proto(recvmsg)
+#ifdef __USE_GNU
+/* Receive up to VLEN messages as described by VMESSAGES from socket FD.
+ Returns the number of messages received or -1 for errors.
+
+ This function is a cancellation point and therefore not marked with
+ __THROW. */
+extern ssize_t recvmmsg (int __fd, struct mmsghdr *__vmessages,
+ size_t vlen, int __flags, struct timespec *__tmo);
+libc_hidden_proto(recvmmsg)
+#endif
/* Put the current value for socket FD's option OPTNAME at protocol level LEVEL
into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the value's
diff --git a/libc/inet/Makefile.in b/libc/inet/Makefile.in
index 332e70e..bed76c3 100644
--- a/libc/inet/Makefile.in
+++ b/libc/inet/Makefile.in
@@ -47,7 +47,8 @@ CSRC-$(UCLIBC_HAS_RESOLVER_SUPPORT) += \
socketcalls_CSRC-y += \
accept.c bind.c connect.c getpeername.c getsockname.c \
getsockopt.c listen.c recv.c recvfrom.c recvmsg.c send.c sendmsg.c \
- sendto.c setsockopt.c shutdown.c socket.c socketpair.c
+ sendto.c setsockopt.c shutdown.c socket.c socketpair.c \
+ recvmmsg.c sendmmsg.c
socketcalls_CSRC-$(UCLIBC_LINUX_SPECIFIC) += accept4.c
CSRC-$(UCLIBC_HAS_SOCKET) += $(socketcalls_CSRC-y) opensock.c
diff --git a/libc/inet/recvmmsg.c b/libc/inet/recvmmsg.c
new file mode 100644
index 0000000..003b5a6
--- /dev/null
+++ b/libc/inet/recvmmsg.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen(a)uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_recvmmsg
+#include "socketcalls.c"
diff --git a/libc/inet/sendmmsg.c b/libc/inet/sendmmsg.c
new file mode 100644
index 0000000..f1557fe
--- /dev/null
+++ b/libc/inet/sendmmsg.c
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2000-2006 Erik Andersen <andersen(a)uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_sendmmsg
+#include "socketcalls.c"
diff --git a/libc/inet/socketcalls.c b/libc/inet/socketcalls.c
index 1fef810..cb28140 100644
--- a/libc/inet/socketcalls.c
+++ b/libc/inet/socketcalls.c
@@ -29,6 +29,8 @@
#define SYS_SENDMSG 16
#define SYS_RECVMSG 17
#define SYS_ACCEPT4 18
+#define SYS_RECVMMSG 19
+#define SYS_SENDMMSG 20
#endif
/* exposed on x86 since Linux commit 9dea5dc921b5f4045a18c63eb92e84dc274d17eb */
@@ -283,6 +285,30 @@ CANCELLABLE_SYSCALL(ssize_t, recvmsg, (int sockfd, struct msghdr *msg, int flags
lt_libc_hidden(recvmsg)
#endif
+#ifdef L_recvmmsg
+static ssize_t __NC(recvmmsg)(int sockfd, struct mmsghdr *msg, size_t vlen,
+ int flags, struct timespec *tmo)
+{
+# ifdef __NR_recvmmsg
+ return (ssize_t)INLINE_SYSCALL(recvmmsg, 5, sockfd, msg, vlen, flags, tmo);
+# else
+ unsigned long args[5];
+
+ args[0] = sockfd;
+ args[1] = (unsigned long) msg;
+ args[2] = vlen;
+ args[3] = flags;
+ args[4] = (unsigned long) tmo;
+ return (ssize_t)__socketcall(SYS_RECVMMSG, args);
+# endif
+}
+CANCELLABLE_SYSCALL(ssize_t, recvmmsg,
+ (int sockfd, struct mmsghdr *msg, size_t vlen, int flags,
+ struct timespec *tmo),
+ (sockfd, msg, vlen, flags, tmo))
+lt_libc_hidden(recvmmsg)
+#endif
+
#ifdef L_send
static ssize_t __NC(send)(int sockfd, const void *buffer, size_t len, int flags)
{
@@ -324,6 +350,28 @@ CANCELLABLE_SYSCALL(ssize_t, sendmsg, (int sockfd, const struct msghdr *msg, int
lt_libc_hidden(sendmsg)
#endif
+#ifdef L_sendmmsg
+static ssize_t __NC(sendmmsg)(int sockfd, struct mmsghdr *msg, size_t vlen,
+ int flags)
+{
+# ifdef __NR_sendmmsg
+ return (ssize_t)INLINE_SYSCALL(sendmmsg, 4, sockfd, msg, vlen, flags);
+# else
+ unsigned long args[4];
+
+ args[0] = sockfd;
+ args[1] = (unsigned long) msg;
+ args[2] = vlen;
+ args[3] = flags;
+ return (ssize_t)__socketcall(SYS_SENDMMSG, args);
+# endif
+}
+CANCELLABLE_SYSCALL(ssize_t, sendmmsg,
+ (int sockfd, struct mmsghdr *msg, size_t vlen, int flags),
+ (sockfd, msg, vlen, flags))
+lt_libc_hidden(sendmmsg)
+#endif
+
#ifdef L_sendto
ssize_t __NC(sendto)(int sockfd, const void *buffer, size_t len, int flags,
const struct sockaddr *to, socklen_t tolen)
diff --git a/libpthread/nptl/Makefile.in b/libpthread/nptl/Makefile.in
index 068eee4..a2f30ac 100644
--- a/libpthread/nptl/Makefile.in
+++ b/libpthread/nptl/Makefile.in
@@ -166,11 +166,13 @@ CFLAGS-readv.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-recv.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-recvfrom.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-recvmsg.c = -fexceptions -fasynchronous-unwind-tables
+CFLAGS-recvmmsg.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-__rt_sigtimedwait.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-__rt_sigwaitinfo.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-select.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-send.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-sendmsg.c = -fexceptions -fasynchronous-unwind-tables
+CFLAGS-sendmmsg.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-sendto.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-sigpause.c = -fexceptions
CFLAGS-sigsuspend.c = -fexceptions -fasynchronous-unwind-tables
--
2.7.4
2
4