From 2fcffe26e815b7125a357c83b59617ab93c16b41 Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Sun, 15 Oct 2017 20:59:34 +0800 Subject: csky: port to uclibc-ng 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 --- 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 + 46 files changed, 2978 insertions(+), 2 deletions(-) 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 (limited to 'libc') diff --git a/libc/string/csky/Makefile b/libc/string/csky/Makefile new file mode 100644 index 000000000..ce5add623 --- /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 000000000..dfa7f64a4 --- /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 000000000..e22f29ebd --- /dev/null +++ b/libc/string/csky/cskyv1/strcmp.S @@ -0,0 +1,185 @@ +#include +#include + +#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 000000000..c2f1e7a0f --- /dev/null +++ b/libc/string/csky/cskyv1/strcpy.S @@ -0,0 +1,139 @@ +#include +#include + +#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 000000000..c112ec01b --- /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 000000000..202da7c8a --- /dev/null +++ b/libc/string/csky/cskyv2/abiv2_strcmp.S @@ -0,0 +1,168 @@ +#include +#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 000000000..20262feae --- /dev/null +++ b/libc/string/csky/cskyv2/abiv2_strcpy.S @@ -0,0 +1,129 @@ +#include +#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 000000000..047645c21 --- /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 000000000..51d258a11 --- /dev/null +++ b/libc/string/csky/memcpy.S @@ -0,0 +1,7 @@ +#include + +#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 000000000..05a88c912 --- /dev/null +++ b/libc/string/csky/strcmp.S @@ -0,0 +1,7 @@ +#include + +#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 000000000..dd3be04b5 --- /dev/null +++ b/libc/string/csky/strcpy.S @@ -0,0 +1,7 @@ +#include + +#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 f4ec4f831..d2fb57e97 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 2d4e466bd..a7ce1ce9b 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 000000000..43dc60a42 --- /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 000000000..704b36aff --- /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 000000000..66ad62617 --- /dev/null +++ b/libc/sysdeps/linux/csky/__longjmp.S @@ -0,0 +1,39 @@ +#include + +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 000000000..346ce8a92 --- /dev/null +++ b/libc/sysdeps/linux/csky/__syscall_error.c @@ -0,0 +1,9 @@ +#include +#include + +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 000000000..231d58f30 --- /dev/null +++ b/libc/sysdeps/linux/csky/bits/atomic.h @@ -0,0 +1,93 @@ +#ifndef __CSKY_ATOMIC_H_ +#define __CSKY_ATOMIC_H_ + +#include +#include + +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 000000000..09af89cd7 --- /dev/null +++ b/libc/sysdeps/linux/csky/bits/endian.h @@ -0,0 +1,10 @@ +#ifndef _ENDIAN_H +# error "Never use directly; include 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 000000000..feacdaded --- /dev/null +++ b/libc/sysdeps/linux/csky/bits/fcntl.h @@ -0,0 +1,193 @@ +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#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 000000000..606fe793d --- /dev/null +++ b/libc/sysdeps/linux/csky/bits/fenv.h @@ -0,0 +1,58 @@ +#ifndef _FENV_H +# error "Never use directly; include 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 000000000..079a01ace --- /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 000000000..80c9d599e --- /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 000000000..d6ab1a22c --- /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),