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 --- MAINTAINERS | 3 + Rules.mak | 15 + extra/Configs/Config.csky | 25 ++ extra/Configs/Config.in | 8 + extra/Configs/defconfigs/csky/defconfig | 1 + include/elf.h | 61 +++ ldso/ldso/csky/dl-startup.h | 115 ++++++ ldso/ldso/csky/dl-syscalls.h | 1 + ldso/ldso/csky/dl-sysdep.h | 89 +++++ ldso/ldso/csky/elfinterp.c | 297 ++++++++++++++ ldso/ldso/csky/read_tp.S | 17 + ldso/ldso/csky/resolve.S | 72 ++++ libc/string/csky/Makefile | 6 + libc/string/csky/cskyv1/memcpy.S | 211 ++++++++++ libc/string/csky/cskyv1/strcmp.S | 185 +++++++++ libc/string/csky/cskyv1/strcpy.S | 139 +++++++ libc/string/csky/cskyv2/abiv2_memcpy.S | 184 +++++++++ libc/string/csky/cskyv2/abiv2_strcmp.S | 168 ++++++++ libc/string/csky/cskyv2/abiv2_strcpy.S | 129 ++++++ libc/string/csky/cskyv2/macro.S | 13 + libc/string/csky/memcpy.S | 7 + libc/string/csky/strcmp.S | 7 + libc/string/csky/strcpy.S | 7 + libc/sysdeps/linux/common/posix_fadvise.c | 2 +- libc/sysdeps/linux/common/posix_fadvise64.c | 2 +- libc/sysdeps/linux/csky/Makefile | 6 + libc/sysdeps/linux/csky/Makefile.arch | 6 + libc/sysdeps/linux/csky/__longjmp.S | 39 ++ libc/sysdeps/linux/csky/__syscall_error.c | 9 + libc/sysdeps/linux/csky/bits/atomic.h | 93 +++++ libc/sysdeps/linux/csky/bits/endian.h | 10 + libc/sysdeps/linux/csky/bits/fcntl.h | 193 +++++++++ libc/sysdeps/linux/csky/bits/fenv.h | 58 +++ libc/sysdeps/linux/csky/bits/kernel_stat.h | 60 +++ libc/sysdeps/linux/csky/bits/kernel_types.h | 47 +++ libc/sysdeps/linux/csky/bits/mathinline.h | 445 +++++++++++++++++++++ libc/sysdeps/linux/csky/bits/setjmp.h | 19 + libc/sysdeps/linux/csky/bits/shm.h | 85 ++++ libc/sysdeps/linux/csky/bits/sigcontextinfo.h | 26 ++ libc/sysdeps/linux/csky/bits/stackinfo.h | 6 + libc/sysdeps/linux/csky/bits/syscalls.h | 113 ++++++ .../sysdeps/linux/csky/bits/uClibc_arch_features.h | 46 +++ libc/sysdeps/linux/csky/bits/wordsize.h | 1 + libc/sysdeps/linux/csky/cacheflush.c | 2 + libc/sysdeps/linux/csky/clone.c | 47 +++ libc/sysdeps/linux/csky/crt1.S | 95 +++++ libc/sysdeps/linux/csky/crti.S | 13 + libc/sysdeps/linux/csky/crtn.S | 11 + libc/sysdeps/linux/csky/csky_clone.S | 20 + libc/sysdeps/linux/csky/jmpbuf-unwind.h | 15 + libc/sysdeps/linux/csky/libc-read_tp.S | 1 + libc/sysdeps/linux/csky/setjmp.S | 43 ++ libc/sysdeps/linux/csky/sys/cachectl.h | 10 + libc/sysdeps/linux/csky/sys/procfs.h | 126 ++++++ libc/sysdeps/linux/csky/sys/ucontext.h | 17 + libc/sysdeps/linux/csky/sys/user.h | 48 +++ libc/sysdeps/linux/csky/sysdep.h | 204 ++++++++++ libc/sysdeps/linux/csky/vfork.S | 6 + libpthread/nptl/sysdeps/csky/Makefile | 6 + libpthread/nptl/sysdeps/csky/Makefile.arch | 7 + libpthread/nptl/sysdeps/csky/dl-tls.h | 9 + libpthread/nptl/sysdeps/csky/libc-tls.c | 18 + libpthread/nptl/sysdeps/csky/pthread_spin_lock.S | 18 + .../nptl/sysdeps/csky/pthread_spin_trylock.S | 16 + libpthread/nptl/sysdeps/csky/pthreaddef.h | 19 + libpthread/nptl/sysdeps/csky/tcb-offsets.sym | 10 + libpthread/nptl/sysdeps/csky/tls.h | 170 ++++++++ .../nptl/sysdeps/unix/sysv/linux/csky/Makefile | 6 + .../sysdeps/unix/sysv/linux/csky/Makefile.arch | 4 + .../unix/sysv/linux/csky/bits/pthreadtypes.h | 181 +++++++++ .../sysdeps/unix/sysv/linux/csky/bits/semaphore.h | 35 ++ .../sysdeps/unix/sysv/linux/csky/createthread.c | 5 + .../nptl/sysdeps/unix/sysv/linux/csky/fork.c | 31 ++ .../sysdeps/unix/sysv/linux/csky/lowlevellock.h | 281 +++++++++++++ .../sysdeps/unix/sysv/linux/csky/pthread_once.c | 100 +++++ .../sysdeps/unix/sysv/linux/csky/sysdep-cancel.h | 33 ++ 76 files changed, 4631 insertions(+), 2 deletions(-) create mode 100644 extra/Configs/Config.csky create mode 100644 extra/Configs/defconfigs/csky/defconfig create mode 100644 ldso/ldso/csky/dl-startup.h create mode 100644 ldso/ldso/csky/dl-syscalls.h create mode 100644 ldso/ldso/csky/dl-sysdep.h create mode 100644 ldso/ldso/csky/elfinterp.c create mode 100644 ldso/ldso/csky/read_tp.S create mode 100644 ldso/ldso/csky/resolve.S create mode 100644 libc/string/csky/Makefile create mode 100644 libc/string/csky/cskyv1/memcpy.S create mode 100644 libc/string/csky/cskyv1/strcmp.S create mode 100644 libc/string/csky/cskyv1/strcpy.S create mode 100644 libc/string/csky/cskyv2/abiv2_memcpy.S create mode 100644 libc/string/csky/cskyv2/abiv2_strcmp.S create mode 100644 libc/string/csky/cskyv2/abiv2_strcpy.S create mode 100644 libc/string/csky/cskyv2/macro.S create mode 100644 libc/string/csky/memcpy.S create mode 100644 libc/string/csky/strcmp.S create mode 100644 libc/string/csky/strcpy.S create mode 100644 libc/sysdeps/linux/csky/Makefile create mode 100644 libc/sysdeps/linux/csky/Makefile.arch create mode 100644 libc/sysdeps/linux/csky/__longjmp.S create mode 100644 libc/sysdeps/linux/csky/__syscall_error.c create mode 100644 libc/sysdeps/linux/csky/bits/atomic.h create mode 100644 libc/sysdeps/linux/csky/bits/endian.h create mode 100644 libc/sysdeps/linux/csky/bits/fcntl.h create mode 100644 libc/sysdeps/linux/csky/bits/fenv.h create mode 100644 libc/sysdeps/linux/csky/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/csky/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/csky/bits/mathinline.h create mode 100644 libc/sysdeps/linux/csky/bits/setjmp.h create mode 100644 libc/sysdeps/linux/csky/bits/shm.h create mode 100644 libc/sysdeps/linux/csky/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/csky/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/csky/bits/syscalls.h create mode 100644 libc/sysdeps/linux/csky/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/csky/bits/wordsize.h create mode 100644 libc/sysdeps/linux/csky/cacheflush.c create mode 100644 libc/sysdeps/linux/csky/clone.c create mode 100644 libc/sysdeps/linux/csky/crt1.S create mode 100644 libc/sysdeps/linux/csky/crti.S create mode 100644 libc/sysdeps/linux/csky/crtn.S create mode 100644 libc/sysdeps/linux/csky/csky_clone.S create mode 100644 libc/sysdeps/linux/csky/jmpbuf-unwind.h create mode 100644 libc/sysdeps/linux/csky/libc-read_tp.S create mode 100644 libc/sysdeps/linux/csky/setjmp.S create mode 100644 libc/sysdeps/linux/csky/sys/cachectl.h create mode 100644 libc/sysdeps/linux/csky/sys/procfs.h create mode 100644 libc/sysdeps/linux/csky/sys/ucontext.h create mode 100644 libc/sysdeps/linux/csky/sys/user.h create mode 100644 libc/sysdeps/linux/csky/sysdep.h create mode 100644 libc/sysdeps/linux/csky/vfork.S create mode 100644 libpthread/nptl/sysdeps/csky/Makefile create mode 100644 libpthread/nptl/sysdeps/csky/Makefile.arch create mode 100644 libpthread/nptl/sysdeps/csky/dl-tls.h create mode 100644 libpthread/nptl/sysdeps/csky/libc-tls.c create mode 100644 libpthread/nptl/sysdeps/csky/pthread_spin_lock.S create mode 100644 libpthread/nptl/sysdeps/csky/pthread_spin_trylock.S create mode 100644 libpthread/nptl/sysdeps/csky/pthreaddef.h create mode 100644 libpthread/nptl/sysdeps/csky/tcb-offsets.sym create mode 100644 libpthread/nptl/sysdeps/csky/tls.h create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/Makefile create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/Makefile.arch create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/bits/pthreadtypes.h create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/bits/semaphore.h create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/createthread.c create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/fork.c create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/lowlevellock.h create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/pthread_once.c create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/csky/sysdep-cancel.h diff --git a/MAINTAINERS b/MAINTAINERS index 642f9034a..d5aa02441 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7,6 +7,9 @@ ARC: Alexey Brodkin Vineet Gupta +CSKY: +Guo Ren + MIPS: Matthew Fortune diff --git a/Rules.mak b/Rules.mak index 0aa29a737..b553cd41c 100644 --- a/Rules.mak +++ b/Rules.mak @@ -453,6 +453,21 @@ ifeq ($(TARGET_ARCH),cris) PIEFLAG_NAME:=-fpie endif +ifeq ($(TARGET_ARCH),csky) + # In csky gas implement, we use $t and $d to detect .text or literal pool. + # So we couldn't strip them for objdump. + STRIP_FLAGS += -K "$$"t -K "$$"d + + CPU_CFLAGS-$(CK610) += -mcpu=ck610f + CPU_CFLAGS-$(CK810) += -mcpu=ck810f + CPU_CFLAGS-$(CK807) += -mcpu=ck807f + + CPU_CFLAGS-$(UCLIBC_HAS_FPU) += -mhard-float + + CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN) += -mlittle-endian + CPU_CFLAGS-$(ARCH_BIG_ENDIAN) += -mbig-endian +endif + ifeq ($(TARGET_ARCH),m68k) # -fPIC is only supported for 68020 and above. It is not supported # for 68000, 68010, or Coldfire. diff --git a/extra/Configs/Config.csky b/extra/Configs/Config.csky new file mode 100644 index 000000000..704f7be1b --- /dev/null +++ b/extra/Configs/Config.csky @@ -0,0 +1,25 @@ +config TARGET_ARCH + string + default "csky" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + select ARCH_HAS_DEPRECATED_SYSCALLS + select ARCH_USE_MMU + select ARCH_HAS_MMU + +choice + prompt "Target Processor Type" + default CK610 + +config CK610 + bool "ck610" +config CK810 + bool "ck810" +config CK807 + bool "ck807" + +endchoice + diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index ce832b55b..b5ee294db 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -22,6 +22,7 @@ choice default TARGET_avr32 if DESIRED_TARGET_ARCH = "avr32" default TARGET_bfin if DESIRED_TARGET_ARCH = "bfin" default TARGET_cris if DESIRED_TARGET_ARCH = "cris" + default TARGET_csky if DESIRED_TARGET_ARCH = "csky" default TARGET_frv if DESIRED_TARGET_ARCH = "frv" default TARGET_h8300 if DESIRED_TARGET_ARCH = "h8300" default TARGET_hppa if DESIRED_TARGET_ARCH = "hppa" @@ -70,6 +71,9 @@ config TARGET_c6x config TARGET_cris bool "cris" +config TARGET_csky + bool "csky" + config TARGET_frv bool "frv" @@ -156,6 +160,10 @@ if TARGET_cris source "extra/Configs/Config.cris" endif +if TARGET_csky +source "extra/Configs/Config.csky" +endif + if TARGET_frv source "extra/Configs/Config.frv" endif diff --git a/extra/Configs/defconfigs/csky/defconfig b/extra/Configs/defconfigs/csky/defconfig new file mode 100644 index 000000000..da837fc29 --- /dev/null +++ b/extra/Configs/defconfigs/csky/defconfig @@ -0,0 +1 @@ +TARGET_csky=y diff --git a/include/elf.h b/include/elf.h index c8488bb3d..fcb546a0f 100644 --- a/include/elf.h +++ b/include/elf.h @@ -1200,6 +1200,67 @@ typedef struct #define ELF64_M_SIZE(info) ELF32_M_SIZE (info) #define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) +/* C-SKY relocs. */ + +#define R_CKCORE_NONE 0 +#define R_CKCORE_ADDR32 1 +#define R_CKCORE_PCRELIMM8BY4 2 +#define R_CKCORE_PCRELIMM11BY2 3 +#define R_CKCORE_PCRELIMM4BY2 4 +#define R_CKCORE_PCREL32 5 +#define R_CKCORE_PCRELJSR_IMM11BY2 6 +#define R_CKCORE_GNU_VTINHERIT 7 +#define R_CKCORE_GNU_VTENTRY 8 +#define R_CKCORE_RELATIVE 9 +#define R_CKCORE_COPY 10 +#define R_CKCORE_GLOB_DAT 11 +#define R_CKCORE_JUMP_SLOT 12 +#define R_CKCORE_GOTOFF 13 +#define R_CKCORE_GOTPC 14 +#define R_CKCORE_GOT32 15 +#define R_CKCORE_PLT32 16 +#define R_CKCORE_ADDRGOT 17 +#define R_CKCORE_ADDRPLT 18 +#define R_CKCORE_PCREL_IMM26BY2 19 +#define R_CKCORE_PCREL_IMM16BY2 20 +#define R_CKCORE_PCREL_IMM16BY4 21 +#define R_CKCORE_PCREL_IMM10BY2 22 +#define R_CKCORE_PCREL_IMM10BY4 23 +#define R_CKCORE_ADDR_HI16 24 +#define R_CKCORE_ADDR_LO16 25 +#define R_CKCORE_GOTPC_HI16 26 +#define R_CKCORE_GOTPC_LO16 27 +#define R_CKCORE_GOTOFF_HI16 28 +#define R_CKCORE_GOTOFF_LO16 29 +#define R_CKCORE_GOT12 30 +#define R_CKCORE_GOT_HI16 31 +#define R_CKCORE_GOT_LO16 32 +#define R_CKCORE_PLT12 33 +#define R_CKCORE_PLT_HI16 34 +#define R_CKCORE_PLT_LO16 35 +#define R_CKCORE_ADDRGOT_HI16 36 +#define R_CKCORE_ADDRGOT_LO16 37 +#define R_CKCORE_ADDRPLT_HI16 38 +#define R_CKCORE_ADDRPLT_LO16 39 +#define R_CKCORE_PCREL_JSR_IMM26BY2 40 +#define R_CKCORE_TOFFSET_LO16 41 +#define R_CKCORE_DOFFSET_LO16 42 +#define R_CKCORE_PCREL_IMM18BY2 43 +#define R_CKCORE_DOFFSET_IMM18 44 +#define R_CKCORE_DOFFSET_IMM18BY2 45 +#define R_CKCORE_DOFFSET_IMM18BY4 46 +#define R_CKCORE_GOTOFF_IMM18 47 +#define R_CKCORE_GOT_IMM18BY4 48 +#define R_CKCORE_PLT_IMM18BY4 49 +#define R_CKCORE_PCREL_IMM7BY4 50 +#define R_CKCORE_TLS_LE32 51 +#define R_CKCORE_TLS_IE32 52 +#define R_CKCORE_TLS_GD32 53 +#define R_CKCORE_TLS_LDM32 54 +#define R_CKCORE_TLS_LDO32 55 +#define R_CKCORE_TLS_DTPMOD32 56 +#define R_CKCORE_TLS_DTPOFF32 57 +#define R_CKCORE_TLS_TPOFF32 58 /* Motorola 68k specific definitions. */ diff --git a/ldso/ldso/csky/dl-startup.h b/ldso/ldso/csky/dl-startup.h new file mode 100644 index 000000000..0a74ab69f --- /dev/null +++ b/ldso/ldso/csky/dl-startup.h @@ -0,0 +1,115 @@ +#ifdef __CSKYABIV2__ + +__asm__ ( + " .text\n\t" + " .globl _start\n\t" + "_start:\n\t" + " mov a0, sp\n\t" + " bsr _dl_start\n\t" + " # Return from _dl_start, user entry point address in a0 \n\t" + " # the code is PIC, so get global offset table\n\t" + " grs gb,.Lgetpc1\n\t" + ".Lgetpc1:\n\t " + " lrw t0, .Lgetpc1@GOTPC\n\t" + " add gb, gb,t0\n\t" + " lrw r5, _dl_skip_args@GOT\n\t" + " ldr.w r5, (gb, r5 << 0)\n\t" + " # get the value of variable _dl_skip_args in r6\n\t" + " ldw r6, (r5, 0)\n\t" + " # get the argc in r7 \n\t" + " ldw r7, (sp, 0)\n\t" + " # adjust the argc, this may be a bug when _dl_skip_args > argc\n\t" + " rsub r6, r7\n\t" + " # adjust the stack\n\t" + " mov r7, r6\n\t" + " lsli r6, 2\n\t" + " # adjust the stack pointer,this may be a bug, " + " # because it must be 8 bytes align" + " addu sp, r6\n\t" + " stw r7, (sp, 0)\n\t" + " lrw r7, _dl_fini@GOTOFF\n\t" + " addu r7, gb\n\t" + " jmp a0" +); +#else +__asm__ ( + " .text\n\t" + " .globl _start\n\t" + "_start:\n\t" + " mov r2, r0\n\t" +# if defined(__ck810__) + " bsr _dl_start\n\t" +#else + " # the code is PIC, so get global offset table\n\t" + " bsr .Lgetpc0\n\t" + ".Lgetpc0:\n\t " + " lrw r14, .Lgetpc0@GOTPC\n\t" + " add r14, r15\n\t" + " lrw r4, _dl_start@GOTOFF\n\t" + " add r4, r14\n\t" + " jsr r4\n\t" +#endif + " # Return from _dl_start, user entry point address in r2 \n\t" + " # the code is PIC, so get global offset table\n\t" + " bsr .Lgetpc1\n\t" + ".Lgetpc1:\n\t " + " lrw r3, .Lgetpc1@GOTPC\n\t" + " add r3, r15\n\t" +# if defined(__ck810__) + " ldw r5, (r3, _dl_skip_args@GOT)\n\t" +#else + " lrw r4, _dl_skip_args@GOT\n\t" + " add r4, r3\n\t" + " ldw r5, (r4, 0)\n\t" +#endif + " # get the value of variable _dl_skip_args in r6\n\t" + " ldw r6, (r5, 0)\n\t" + " # get the argc in r7 \n\t" + " ldw r7, (r0, 0)\n\t" + " # adjust the argc, this may be a bug when _dl_skip_args > argc\n\t" + " rsub r6, r7\n\t" + " # adjust the stack\n\t" + " mov r7, r6\n\t" + " lsli r6, 2\n\t" + " # adjust the stack pointer,this may be a bug, " + " # because it must be 8 bytes align" + " addu r0, r6\n\t" + " stw r7, (r0, 0)\n\t" + " lrw r7, _dl_fini@GOTOFF\n\t" + " addu r7, r3\n\t" + " jmp r2" +); + +#endif + +/* Get a pointer to the argv array. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1) + +/* Function calls are not safe until the GOT relocations have been done. */ +#define NO_FUNCS_BEFORE_BOOTSTRAP +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab) +{ + switch (ELF32_R_TYPE(rpnt->r_info)) + { + case R_CKCORE_RELATIVE: + *reloc_addr = load_addr + rpnt->r_addend; + break; + case R_CKCORE_GLOB_DAT: + case R_CKCORE_JUMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_CKCORE_ADDR32: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_CKCORE_NONE: + break; + + default: + _dl_exit(1); + } +} + + diff --git a/ldso/ldso/csky/dl-syscalls.h b/ldso/ldso/csky/dl-syscalls.h new file mode 100644 index 000000000..f40c4fd31 --- /dev/null +++ b/ldso/ldso/csky/dl-syscalls.h @@ -0,0 +1 @@ +/* stub for arch-specific syscall issues */ diff --git a/ldso/ldso/csky/dl-sysdep.h b/ldso/ldso/csky/dl-sysdep.h new file mode 100644 index 000000000..c78dd81bc --- /dev/null +++ b/ldso/ldso/csky/dl-sysdep.h @@ -0,0 +1,89 @@ +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA + +#include +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +do { \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} while(0) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_MCORE +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "csky" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* 65536 bytes alignment */ +#define PAGE_ALIGN 0xfffff000 /* need modify */ +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_CKCORE_JUMP_SLOT || (type) == R_CKCORE_TLS_DTPMOD32 \ + || (type) == R_CKCORE_TLS_DTPOFF32 || (type) == R_CKCORE_TLS_TPOFF32) \ + * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_CKCORE_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __inline__ Elf32_Addr elf_machine_dynamic (void) attribute_unused; +static __inline__ Elf32_Addr +elf_machine_dynamic (void) +{ + register Elf32_Addr *got __asm__ ("gb"); /* need modify */ + return *got; +} + +/* this funtion will be called only when the auxvt[AT_BASE].a_un.a_val == 0 + so it normal not be called, we should define a default address of the interprrter load */ +static __inline__ Elf32_Addr elf_machine_load_address (void) attribute_unused; +static __inline__ Elf32_Addr +elf_machine_load_address (void) +{ +#ifdef __CSKYABIV2__ + extern Elf32_Addr internal_function __dl_start (void *) __asm__ ("_dl_start"); + Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; + Elf32_Addr pcrel_addr; + __asm__ ("grs %0,_dl_start\n" : "=r" (pcrel_addr)); +#else + extern Elf32_Addr internal_function __start_flag (void *) __asm__ ("start_flag"); + Elf32_Addr got_addr = (Elf32_Addr) &__start_flag; + Elf32_Addr pcrel_addr; + __asm__ ("subi sp,8\n" \ + "stw lr,(sp,0)\n" \ + "bsr start_flag\n" \ + "start_flag:" \ + "mov %0, lr\n" \ + "ldw lr,(sp,0)\n" \ + "addi sp,8\n" \ + : "=r" (pcrel_addr)); +#endif + return pcrel_addr - got_addr; + +} + +/* some relocation information are machine special */ +static __inline__ void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela *rpnt = (void *) rel_addr; + --rpnt; + do { + Elf32_Addr *reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); /* maybe need modify */ +} + diff --git a/ldso/ldso/csky/elfinterp.c b/ldso/ldso/csky/elfinterp.c new file mode 100644 index 000000000..1469c28f1 --- /dev/null +++ b/ldso/ldso/csky/elfinterp.c @@ -0,0 +1,297 @@ +#include "ldso.h" + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + int symtab_index; + //char *rel_tab; + Elf32_Sym *sym_tab; + char *str_tab; + char *sym_name; + char *sym_addr; + char **reloc_addr; + + this_reloc = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc += reloc_entry; + //this_reloc = (ELF_RELOC *)(intptr_t)(rel_tab + reloc_entry); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + sym_tab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + str_tab = (char *)tpnt->dynamic_info[DT_STRTAB]; + sym_name = str_tab + sym_tab[symtab_index].st_name; + + reloc_addr = (char **)((unsigned long)this_reloc->r_offset + + (unsigned long)tpnt->loadaddr); + + sym_addr = _dl_find_hash(sym_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + + if (unlikely(!sym_addr)) { + _dl_dprintf(2, "%s: 1can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, sym_name, tpnt->libname); + _dl_exit(1); + } + + *reloc_addr = sym_addr; + + return (unsigned long)sym_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem*scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem*scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)(intptr_t)rel_addr; + rel_size /= sizeof(ELF_RELOC); + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + if (res == 0) + continue; + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + if (unlikely(res < 0)) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "2can't handle reloc type '%s' in lib '%s'\n", + _dl_reltypes(reloc_type), tpnt->libname); +#else + _dl_dprintf(2, "3can't handle reloc type %x in lib '%s'\n", + reloc_type, tpnt->libname); +#endif + return res; + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "4can't resolve symbol in lib '%s'.\n", tpnt->libname); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr; + struct symbol_ref sym_ref; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif +#if defined USE_TLS && USE_TLS + struct elf_resolve *tls_tpnt = NULL; +#endif +#if defined(__CSKYABIV2__) + unsigned int insn_opcode = 0x0; + unsigned short *opcode16_addr; +#endif + + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); +#if defined(__CSKYABIV2__) + opcode16_addr = (unsigned short *)reloc_addr; +#endif + reloc_type = ELF32_R_TYPE(rpnt->r_info); + + if (reloc_type == R_CKCORE_NONE) + return 0; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symname = strtab + symtab[symtab_index].st_name; + if (symtab_index) { + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + // if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) + if (!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS) + && (ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) + return 1; +#if defined USE_TLS && USE_TLS + tls_tpnt = sym_ref.tpnt; +#endif + }else{ + /* + * Relocs against STN_UNDEF are usually treated as using a + * symbol value of zero, and using the module containing the + * reloc itself. + */ + symbol_addr = symtab[symtab_index].st_name; +#if defined USE_TLS && USE_TLS + tls_tpnt = tpnt; +#endif + } +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { /* need modify */ + case R_CKCORE_NONE: + case R_CKCORE_PCRELJSR_IMM11BY2: + break; + case R_CKCORE_ADDR32: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_CKCORE_GLOB_DAT: + case R_CKCORE_JUMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_CKCORE_RELATIVE: + *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend; + break; +#if defined(__CSKYABIV2__) + case R_CKCORE_ADDR_HI16: + insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1)); + insn_opcode = (insn_opcode & 0xffff0000) + | (((symbol_addr + rpnt->r_addend) >> 16) & 0xffff); + *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16); + *opcode16_addr = (unsigned short)(insn_opcode & 0xffff); + break; + case R_CKCORE_ADDR_LO16: + insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1)); + insn_opcode = (insn_opcode & 0xffff0000) + | ((symbol_addr + rpnt->r_addend) & 0xffff); + *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16); + *opcode16_addr = (unsigned short)(insn_opcode & 0xffff); + break; + case R_CKCORE_PCREL_IMM26BY2: + { + unsigned int offset = ((symbol_addr + rpnt->r_addend - + (unsigned int)reloc_addr) >> 1); + insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1)); + if (offset > 0x3ffffff){ + _dl_dprintf(2, "%s:The reloc R_CKCORE_PCREL_IMM26BY2 cannot reach the symbol '%s'.\n", _dl_progname, symname); + _dl_exit(1); + } + insn_opcode = (insn_opcode & ~0x3ffffff) | offset; + *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16); + *opcode16_addr = (unsigned short)(insn_opcode & 0xffff); + break; + } + case R_CKCORE_PCREL_JSR_IMM26BY2: + break; +#endif + case R_CKCORE_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\n%s move %d bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + symtab[symtab_index].st_size); + } + break; +#if defined USE_TLS && USE_TLS + case R_CKCORE_TLS_DTPMOD32: + *reloc_addr = tls_tpnt->l_tls_modid; + break; + case R_CKCORE_TLS_DTPOFF32: + *reloc_addr += symbol_addr; + break; + case R_CKCORE_TLS_TPOFF32: + CHECK_STATIC_TLS ((struct link_map *) tls_tpnt); + *reloc_addr += tls_tpnt->l_tls_offset + symbol_addr; + break; +#endif + default: + return -1; + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + unsigned long *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_CKCORE_NONE: + case R_CKCORE_PCRELJSR_IMM11BY2: + break; + case R_CKCORE_JUMP_SLOT: + *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend; + break; + default: + return -1; + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + struct r_scope_elem *scope, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/ldso/ldso/csky/read_tp.S b/ldso/ldso/csky/read_tp.S new file mode 100644 index 000000000..ef8d509d5 --- /dev/null +++ b/ldso/ldso/csky/read_tp.S @@ -0,0 +1,17 @@ +#include + +#ifndef NOT_IN_libc +.global __read_tp +#else +.hidden __read_tp +#endif + +ENTRY (__read_tp) +#ifdef __CSKYABIV2__ + mov a0, tls +#else + trap 3 +#endif + rts +END (__read_tp) + diff --git a/ldso/ldso/csky/resolve.S b/ldso/ldso/csky/resolve.S new file mode 100644 index 000000000..46a436345 --- /dev/null +++ b/ldso/ldso/csky/resolve.S @@ -0,0 +1,72 @@ +/* + * This function is not called directly. It is jumped when attempting to use a + * symbol that has not yet been resolved. + * + *.plt*: + * subi r0, 32 + * stw r2, (r0, 0) + * stw r3, (r0, 4) + * lrw r3, #offset + * ldw r2, (gb, 8) + * jmp r2 + */ + +.import _dl_linux_resolver + +.text +.globl _dl_linux_resolve +.type _dl_linux_resolve,@function + +_dl_linux_resolve: +#ifdef __CSKYABIV1__ + stw r4, (r0, 8) + stw r5, (r0, 12) + stw r6, (r0, 16) + stw r7, (r0, 20) + stw r15,(r0, 24) + # load the ID of this module + ldw r2, (gb, 4) + # r2 = id, r3 = offset(do it in plt*) +#ifdef __PIC__ + # get global offset table address_ + bsr .L2 +.L2: + lrw r7, .L2@GOTPC + add r7, r15 + # get the address of function (_dl_linux_resolver) in got table + lrw r6, _dl_linux_resolver@GOT + add r6, r7 + ldw r5, (r6, 0) + jsr r5 +#else /* no __PIC__ */ + jsri _dl_linux_resolver /* need modify */ +#endif + # Return from _dl_linux_resolver, the address of function is in r2 + mov r1, r2 + # Restore the registers + ldw r2, (r0, 0) + ldw r3, (r0, 4) + ldw r4, (r0, 8) + ldw r5, (r0, 12) + ldw r6, (r0, 16) + ldw r7, (r0, 20) + ldw r15,(r0, 24) + # Restore the r0, because r0 is subtracted in PLT table + addi r0, 32 + # The address of function is in r1, call the function without saving pc + jmp r1 +#else /* __CSKYABIV1__ */ + subi sp, 20 + stm a0-a3, (sp) + stw lr, (sp, 16) + # a0 = id, a1 = offset(do it in plt*) + ldw a0, (gb, 4) + mov a1, t1 + bsr _dl_linux_resolver + mov t0, a0 + ldw lr, (sp, 16) + ldm a0-a3, (sp) + addi sp, 20 + jmp t0 + +#endif diff --git a/libc/string/csky/Makefile b/libc/string/csky/Makefile new file mode 100644 index 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;