diff options
author | Guo Ren <ren_guo@c-sky.com> | 2017-10-15 20:59:34 +0800 |
---|---|---|
committer | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2017-11-19 09:20:11 +0100 |
commit | 2fcffe26e815b7125a357c83b59617ab93c16b41 (patch) | |
tree | fe5a973dc4bbf38bce8468a4497f5f656f082a9f /libc | |
parent | 9e38e0aa45cca21d5023d0af94377f0e1e41d2f4 (diff) |
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 <ren_guo@c-sky.com>
Diffstat (limited to 'libc')
46 files changed, 2978 insertions, 2 deletions
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 <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 000000000..c2f1e7a0f --- /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 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 <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 000000000..20262feae --- /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 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 <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 000000000..05a88c912 --- /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 000000000..dd3be04b5 --- /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 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 <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 000000000..346ce8a92 --- /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 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 <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 000000000..09af89cd7 --- /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 000000000..feacdaded --- /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 000000000..606fe793d --- /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 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), (__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 000000000..c818ec9dc --- /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 000000000..bfb44bb4c --- /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 000000000..b7e08cfc9 --- /dev/null +++ b/libc/sysdeps/linux/csky/bits/sigcontextinfo.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT int _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) (ctx)->sc_pc) +#define GET_FRAME(ctx) ((void *) __builtin_frame_address (1)) +#define GET_STACK(ctx) ((void *) (ctx)->sc_usp) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/csky/bits/stackinfo.h b/libc/sysdeps/linux/csky/bits/stackinfo.h new file mode 100644 index 000000000..aaf980752 --- /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 000000000..04d01f4ca --- /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 000000000..ca898ee18 --- /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 000000000..1b5842adb --- /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 000000000..7762c7332 --- /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 000000000..97c30d027 --- /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 000000000..ae73843fb --- /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 000000000..e85a81cb1 --- /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 000000000..3814f307e --- /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 000000000..83604691f --- /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 000000000..30e39f451 --- /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 000000000..1974cba25 --- /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 000000000..daadcb318 --- /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 000000000..0d45bf07f --- /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 000000000..91c1388d7 --- /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 000000000..59176882c --- /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 000000000..4ab1972a0 --- /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 000000000..2fcff684e --- /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 000000000..a28bb32fa --- /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) + |