diff --git a/ChangeLog.tile b/ChangeLog.tile new file mode 100644 index 0000000000..7e97f5fa42 --- /dev/null +++ b/ChangeLog.tile @@ -0,0 +1,134 @@ +2011-12-03 Chris Metcalf + + * data/c++-types-tile-linux-gnu.data: New file. + * sysdeps/tile/Implies: New file. + * sysdeps/tile/Makefile: New file. + * sysdeps/tile/Versions: New file. + * sysdeps/tile/__longjmp.S: New file. + * sysdeps/tile/__tls_get_addr.S: New file. + * sysdeps/tile/_mcount.S: New file. + * sysdeps/tile/abort-instr.h: New file. + * sysdeps/tile/backtrace.c: New file. + * sysdeps/tile/bits/atomic.h: New file. + * sysdeps/tile/bits/byteswap.h: New file. + * sysdeps/tile/bits/endian.h: New file. + * sysdeps/tile/bits/fenv.h: New file. + * sysdeps/tile/bits/link.h: New file. + * sysdeps/tile/bits/mathdef.h: New file. + * sysdeps/tile/bits/mathinline.h: New file. + * sysdeps/tile/bits/setjmp.h: New file. + * sysdeps/tile/bsd-_setjmp.S: New file. + * sysdeps/tile/bsd-setjmp.S: New file. + * sysdeps/tile/bzero.S: New file. + * sysdeps/tile/dl-lookupcfg.h: New file. + * sysdeps/tile/dl-machine.h: New file. + * sysdeps/tile/dl-runtime.c: New file. + * sysdeps/tile/dl-start.S: New file. + * sysdeps/tile/dl-tls.c: New file. + * sysdeps/tile/dl-tls.h: New file. + * sysdeps/tile/dl-trampoline.S: New file. + * sysdeps/tile/elf/start.S: New file. + * sysdeps/tile/fegetenv.c: New file. + * sysdeps/tile/fegetround.c: New file. + * sysdeps/tile/feholdexcpt.c: New file. + * sysdeps/tile/fesetenv.c: New file. + * sysdeps/tile/fesetround.c: New file. + * sysdeps/tile/feupdateenv.c: New file. + * sysdeps/tile/ffs.c: New file. + * sysdeps/tile/ffsll.c: New file. + * sysdeps/tile/gccframe.h: New file. + * sysdeps/tile/jmpbuf-offsets.h: New file. + * sysdeps/tile/jmpbuf-unwind.h: New file. + * sysdeps/tile/ldsodefs.h: New file. + * sysdeps/tile/machine-gmon.h: New file. + * sysdeps/tile/nptl/Makefile: New file. + * sysdeps/tile/nptl/pthread_spin_lock.c: New file. + * sysdeps/tile/nptl/pthread_spin_trylock.c: New file. + * sysdeps/tile/nptl/pthreaddef.h: New file. + * sysdeps/tile/nptl/tcb-offsets.sym: New file. + * sysdeps/tile/nptl/tls.h: New file. + * sysdeps/tile/preconfigure: New file. + * sysdeps/tile/s_fma.c: New file. + * sysdeps/tile/s_fmaf.c: New file. + * sysdeps/tile/setjmp.S: New file. + * sysdeps/tile/shlib-versions: New file. + * sysdeps/tile/stackinfo.h: New file. + * sysdeps/tile/sysdep.h: New file. + * sysdeps/tile/tilegx/bits/atomic.h: New file. + * sysdeps/tile/tilegx/bits/wordsize.h: New file. + * sysdeps/tile/tilegx/memchr.c: New file. + * sysdeps/tile/tilegx/memcpy.c: New file. + * sysdeps/tile/tilegx/memset.c: New file. + * sysdeps/tile/tilegx/memusage.h: New file. + * sysdeps/tile/tilegx/rawmemchr.c: New file. + * sysdeps/tile/tilegx/strchr.c: New file. + * sysdeps/tile/tilegx/strchrnul.c: New file. + * sysdeps/tile/tilegx/string-endian.h: New file. + * sysdeps/tile/tilegx/strlen.c: New file. + * sysdeps/tile/tilegx/strrchr.c: New file. + * sysdeps/tile/tilegx/tilegx32/Implies: New file. + * sysdeps/tile/tilegx/tilegx64/Implies: New file. + * sysdeps/tile/tilepro/Implies: New file. + * sysdeps/tile/tilepro/bits/atomic.h: New file. + * sysdeps/tile/tilepro/bits/wordsize.h: New file. + * sysdeps/tile/tilepro/memchr.c: New file. + * sysdeps/tile/tilepro/memcpy.S: New file. + * sysdeps/tile/tilepro/memset.c: New file. + * sysdeps/tile/tilepro/memusage.h: New file. + * sysdeps/tile/tilepro/rawmemchr.c: New file. + * sysdeps/tile/tilepro/strchr.c: New file. + * sysdeps/tile/tilepro/strchrnul.c: New file. + * sysdeps/tile/tilepro/strlen.c: New file. + * sysdeps/tile/tilepro/strrchr.c: New file. + * sysdeps/tile/tls-macros.h: New file. + * sysdeps/tile/tst-audit.h: New file. + * sysdeps/unix/sysv/linux/tile/Makefile: New file. + * sysdeps/unix/sysv/linux/tile/Versions: New file. + * sysdeps/unix/sysv/linux/tile/bits/environments.h: New file. + * sysdeps/unix/sysv/linux/tile/bits/local_lim.h: New file. + * sysdeps/unix/sysv/linux/tile/bits/mman.h: New file. + * sysdeps/unix/sysv/linux/tile/bits/mman.h~: New file. + * sysdeps/unix/sysv/linux/tile/bits/sigaction.h: New file. + * sysdeps/unix/sysv/linux/tile/bits/siginfo.h: New file. + * sysdeps/unix/sysv/linux/tile/cacheflush.c: New file. + * sysdeps/unix/sysv/linux/tile/configure: New file. + * sysdeps/unix/sysv/linux/tile/configure.in: New file. + * sysdeps/unix/sysv/linux/tile/getcontext.S: New file. + * sysdeps/unix/sysv/linux/tile/kernel-features.h: New file. + * sysdeps/unix/sysv/linux/tile/makecontext.c: New file. + * sysdeps/unix/sysv/linux/tile/nptl/Makefile: New file. + * sysdeps/unix/sysv/linux/tile/nptl/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/tile/nptl/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/tile/nptl/clone.S: New file. + * sysdeps/unix/sysv/linux/tile/nptl/createthread.c: New file. + * sysdeps/unix/sysv/linux/tile/nptl/fork.c: New file. + * sysdeps/unix/sysv/linux/tile/nptl/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/tile/nptl/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/tile/nptl/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/tile/nptl/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/tile/nptl/vfork.S: New file. + * sysdeps/unix/sysv/linux/tile/nptl/waitpid.S: New file. + * sysdeps/unix/sysv/linux/tile/profil-counter.h: New file. + * sysdeps/unix/sysv/linux/tile/set_dataplane.c: New file. + * sysdeps/unix/sysv/linux/tile/setcontext.S: New file. + * sysdeps/unix/sysv/linux/tile/sigcontextinfo.h: New file. + * sysdeps/unix/sysv/linux/tile/swapcontext.S: New file. + * sysdeps/unix/sysv/linux/tile/sys/cachectl.h: New file. + * sysdeps/unix/sysv/linux/tile/sys/dataplane.h: New file. + * sysdeps/unix/sysv/linux/tile/sys/procfs.h: New file. + * sysdeps/unix/sysv/linux/tile/sys/ptrace.h: New file. + * sysdeps/unix/sysv/linux/tile/sys/reg.h: New file. + * sysdeps/unix/sysv/linux/tile/sys/ucontext.h: New file. + * sysdeps/unix/sysv/linux/tile/sys/user.h: New file. + * sysdeps/unix/sysv/linux/tile/syscall.S: New file. + * sysdeps/unix/sysv/linux/tile/sysdep.c: New file. + * sysdeps/unix/sysv/linux/tile/sysdep.h: New file. + * sysdeps/unix/sysv/linux/tile/tilegx/ioctl.S: New file. + * sysdeps/unix/sysv/linux/tile/tilegx/ldconfig.h: New file. + * sysdeps/unix/sysv/linux/tile/tilegx/register-dump.h: New file. + * sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/Implies: New file. + * sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/Implies: New file. + * sysdeps/unix/sysv/linux/tile/tilepro/Implies: New file. + * sysdeps/unix/sysv/linux/tile/tilepro/ldconfig.h: New file. + * sysdeps/unix/sysv/linux/tile/tilepro/register-dump.h: New file. + * sysdeps/unix/sysv/linux/tile/ucontext_i.h: New file. diff --git a/data/c++-types-tile-linux-gnu.data b/data/c++-types-tile-linux-gnu.data new file mode 100644 index 0000000000..303f4570c8 --- /dev/null +++ b/data/c++-types-tile-linux-gnu.data @@ -0,0 +1,67 @@ +blkcnt64_t:x +blkcnt_t:l +blksize_t:i +caddr_t:Pc +clockid_t:i +clock_t:l +daddr_t:i +dev_t:y +fd_mask:l +fsblkcnt64_t:y +fsblkcnt_t:m +fsfilcnt64_t:y +fsfilcnt_t:m +fsid_t:8__fsid_t +gid_t:j +id_t:j +ino64_t:y +ino_t:m +int16_t:s +int32_t:i +int64_t:x +int8_t:a +intptr_t:i +key_t:i +loff_t:x +mode_t:j +nlink_t:j +off64_t:x +off_t:l +pid_t:i +pthread_attr_t:14pthread_attr_t +pthread_barrier_t:17pthread_barrier_t +pthread_barrierattr_t:21pthread_barrierattr_t +pthread_cond_t:14pthread_cond_t +pthread_condattr_t:18pthread_condattr_t +pthread_key_t:j +pthread_mutex_t:15pthread_mutex_t +pthread_mutexattr_t:19pthread_mutexattr_t +pthread_once_t:i +pthread_rwlock_t:16pthread_rwlock_t +pthread_rwlockattr_t:20pthread_rwlockattr_t +pthread_spinlock_t:i +pthread_t:m +quad_t:x +register_t:i +rlim64_t:y +rlim_t:m +sigset_t:10__sigset_t +size_t:j +socklen_t:j +ssize_t:i +suseconds_t:l +time_t:l +u_char:h +uid_t:j +uint:j +u_int:j +u_int16_t:t +u_int32_t:j +u_int64_t:y +u_int8_t:h +ulong:m +u_long:m +u_quad_t:y +useconds_t:j +ushort:t +u_short:t diff --git a/sysdeps/tile/Implies b/sysdeps/tile/Implies new file mode 100644 index 0000000000..5b29b26128 --- /dev/null +++ b/sysdeps/tile/Implies @@ -0,0 +1,2 @@ +ieee754/dbl-64 +ieee754/flt-32 diff --git a/sysdeps/tile/Makefile b/sysdeps/tile/Makefile new file mode 100644 index 0000000000..08c3385502 --- /dev/null +++ b/sysdeps/tile/Makefile @@ -0,0 +1,18 @@ +# We don't support long doubles as a distinct type. We don't need to set +# this variable; it's here mostly for documentational purposes. + +long-double-fcts = no + +ifeq ($(subdir),gmon) +sysdep_routines += _mcount +endif + +ifeq ($(subdir),elf) +# Extra shared linker files to link only into dl-allobjs.so. +sysdep-rtld-routines += dl-start __tls_get_addr +endif + +ifeq ($(subdir),csu) +# Avoid .cfi_startproc/endproc markers when creating init and fini pieces. +CFLAGS-initfini.s += -fno-asynchronous-unwind-tables +endif diff --git a/sysdeps/tile/Versions b/sysdeps/tile/Versions new file mode 100644 index 0000000000..b275d7ff3b --- /dev/null +++ b/sysdeps/tile/Versions @@ -0,0 +1,6 @@ +libc { + GLIBC_2.12 { + # name requested by gcc community. + __mcount; + } +} diff --git a/sysdeps/tile/__longjmp.S b/sysdeps/tile/__longjmp.S new file mode 100644 index 0000000000..f31c662499 --- /dev/null +++ b/sysdeps/tile/__longjmp.S @@ -0,0 +1,58 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* PL to return to via iret in longjmp */ +#define RETURN_PL 0 + + .text +ENTRY (__longjmp) + FEEDBACK_ENTER(__longjmp) + +#define RESTORE(r) { LD r, r0 ; ADDI_PTR r0, r0, REGSIZE } + FOR_EACH_CALLEE_SAVED_REG(RESTORE) + + /* Make longjmp(buf, 0) return "1" instead. + At the same time, construct our iret context; we set ICS so + we can validly load EX_CONTEXT for iret without being + interrupted halfway through. */ + { + LD r2, r0 /* retrieve ICS bit from jmp_buf */ + movei r3, 1 + CMPEQI r0, r1, 0 + } + { + mtspr INTERRUPT_CRITICAL_SECTION, r3 + shli r2, r2, SPR_EX_CONTEXT_0_1__ICS_SHIFT + } + { + mtspr EX_CONTEXT_0_0, lr + ori r2, r2, RETURN_PL + } + { + or r0, r1, r0 + mtspr EX_CONTEXT_0_1, r2 + } + iret + jrp lr /* Keep the backtracer happy. */ +END (__longjmp) diff --git a/sysdeps/tile/__tls_get_addr.S b/sysdeps/tile/__tls_get_addr.S new file mode 100644 index 0000000000..ca491c51b7 --- /dev/null +++ b/sysdeps/tile/__tls_get_addr.S @@ -0,0 +1,150 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifdef _LP64 +#define LOG_SIZEOF_DTV_T 4 +#else +#define LOG_SIZEOF_DTV_T 3 +#endif + +/* On entry, r0 points to two words, the module and the offset. + On return, r0 holds the pointer to the relevant TLS memory. + Only registers r25..r29 are clobbered by the call. */ + + .text +ENTRY (__tls_get_addr) + { + lnk r25 + ADDI_PTR r27, tp, DTV_OFFSET + } +.Llnk: +#ifdef __tilegx__ + { + LD_PTR r27, r27 /* r27 = THREAD_DTV() */ + moveli r26, hw1_last(_rtld_local + TLS_GENERATION_OFFSET - .Llnk) + } + shl16insli r26, r26, hw0(_rtld_local + TLS_GENERATION_OFFSET - .Llnk) + { + ADD_PTR r25, r25, r26 + LD_PTR r26, r0 /* r26 = ti_module */ + } +#else + { + LD_PTR r27, r27 /* r27 = THREAD_DTV() */ + addli r25, r25, lo16(_rtld_local + TLS_GENERATION_OFFSET - .Llnk) + } + { + auli r25, r25, ha16(_rtld_local + TLS_GENERATION_OFFSET - .Llnk) + LD_PTR r26, r0 /* r26 = ti_module */ + } +#endif + LD_PTR r25, r25 /* r25 = DL(dl_tls_generation) */ + { + LD_PTR r28, r27 /* r28 = THREAD_DTV()->counter */ + ADDI_PTR r29, r0, __SIZEOF_POINTER__ + } + { + LD_PTR r29, r29 /* r29 = ti_offset */ + CMPEQ r25, r28, r25 /* r25 nonzero if generation OK */ + shli r28, r26, LOG_SIZEOF_DTV_T /* byte index into dtv array */ + } + { + BEQZ r25, .Lslowpath + CMPEQI r25, r26, -1 /* r25 nonzero if ti_module invalid */ + } + { + BNEZ r25, .Lslowpath + ADD_PTR r28, r28, r27 /* pointer into module array */ + } + LD_PTR r26, r28 /* r26 = module TLS pointer */ + { + ADD_PTR r0, r26, r29 + jrp lr + } + +.Lslowpath: + { + ST sp, lr + ADDLI_PTR r29, sp, - (25 * REGSIZE) + } + cfi_offset (lr, 0) + { + ST r29, sp + ADDLI_PTR sp, sp, - (26 * REGSIZE) + } + cfi_def_cfa_offset (26 * REGSIZE) + ADDI_PTR r29, sp, (2 * REGSIZE) + { ST r29, r1; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r2; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r3; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r4; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r5; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r6; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r7; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r8; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r9; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r10; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r11; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r12; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r13; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r14; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r15; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r16; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r17; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r18; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r19; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r20; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r21; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r22; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r23; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r24; ADDI_PTR r29, r29, REGSIZE } + .hidden __tls_get_addr_slow + jal __tls_get_addr_slow + ADDI_PTR r29, sp, (2 * REGSIZE) + { LD r1, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r2, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r3, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r4, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r5, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r6, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r7, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r8, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r9, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r10, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r11, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r12, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r13, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r14, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r15, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r16, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r17, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r18, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r19, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r20, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r21, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r22, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r23, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r24, r29; ADDLI_PTR sp, sp, (26 * REGSIZE) } + cfi_def_cfa_offset (0) + LD lr, sp + jrp lr +END (__tls_get_addr) diff --git a/sysdeps/tile/_mcount.S b/sysdeps/tile/_mcount.S new file mode 100644 index 0000000000..63708a1ddd --- /dev/null +++ b/sysdeps/tile/_mcount.S @@ -0,0 +1,88 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + Based on work contributed by David Mosberger (davidm@cs.arizona.edu). + + 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. */ + +/* Assembly stub to invoke __mcount_internal(). Compiler-generated + code calls mcount after executing a function's prologue, placing + the "lr" register in "r10" for the call. As a result "lr" is the + function that invoked mcount, and "r10" is mcount's caller's + caller. However, we have to save all the parameter registers here + before invoking _mcount_internal. Callee-save and temporary + registers need no special attention. We save r10 and restore it to + lr on the way out, to properly handle the case of ENTRY() in + assembly code, before lr is saved. We use the name __mcount since + the gcc community prefers using the reserved namespace. */ + +#include + + .text +ENTRY(__mcount) + { + ST sp, lr + ADDI_PTR r29, sp, - (12 * REGSIZE) + } + cfi_offset (lr, 0) + { + ADDI_PTR sp, sp, - (13 * REGSIZE) + ST r29, sp + ADDI_PTR r29, r29, REGSIZE + } + cfi_def_cfa_offset (13 * REGSIZE) + { ST r29, r0; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r1; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r2; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r3; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r4; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r5; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r6; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r7; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r8; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r9; ADDI_PTR r29, r29, REGSIZE } + { ST r29, r10; ADDI_PTR r29, r29, REGSIZE; move r0, r10 } + { + move r1, lr + jal __mcount_internal + } + { + ADDI_PTR r29, sp, (2 * REGSIZE) + } + { LD r0, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r1, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r2, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r3, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r4, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r5, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r6, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r7, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r8, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r9, r29; ADDI_PTR r29, r29, REGSIZE } + { LD r10, r29; ADDI_PTR sp, sp, (13 * REGSIZE) } + cfi_def_cfa_offset (0) + { + LD lr, sp + } + { + move lr, r10 + jrp lr + } +END(__mcount) + +#undef mcount +weak_alias (__mcount, _mcount) /* exported in gmon/Versions */ +weak_alias (__mcount, mcount) /* exported in stdlib/Versions */ diff --git a/sysdeps/tile/abort-instr.h b/sysdeps/tile/abort-instr.h new file mode 100644 index 0000000000..0f57da5198 --- /dev/null +++ b/sysdeps/tile/abort-instr.h @@ -0,0 +1,2 @@ +/* An instruction which should crash any program is `hlt'. */ +#define ABORT_INSTRUCTION asm ("ill") diff --git a/sysdeps/tile/backtrace.c b/sysdeps/tile/backtrace.c new file mode 100644 index 0000000000..297029456d --- /dev/null +++ b/sysdeps/tile/backtrace.c @@ -0,0 +1 @@ +#include diff --git a/sysdeps/tile/bits/atomic.h b/sysdeps/tile/bits/atomic.h new file mode 100644 index 0000000000..a0fdb6fbc0 --- /dev/null +++ b/sysdeps/tile/bits/atomic.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +/* The sub-architecture headers provide definitions for these macros + that work for "int" and "long" size values only: + + atomic_compare_and_exchange_val_acq() + atomic_exchange_acq() + atomic_exchange_and_add() + atomic_and_val() + atomic_or_val() + atomic_decrement_if_positive() [tilegx only] + + Here we provide generic definitions true for all Tilera chips. */ + +#include +#include + +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; + +/* Barrier macro. */ +#define atomic_full_barrier() __sync_synchronize() + +/* APIs with "release" semantics. */ +#define atomic_compare_and_exchange_val_rel(mem, n, o) \ + ({ \ + atomic_full_barrier (); \ + atomic_compare_and_exchange_val_acq ((mem), (n), (o)); \ + }) +#define atomic_compare_and_exchange_bool_rel(mem, n, o) \ + ({ \ + atomic_full_barrier (); \ + atomic_compare_and_exchange_bool_acq ((mem), (n), (o)); \ + }) +#define atomic_exchange_rel(mem, n) \ + ({ \ + atomic_full_barrier (); \ + atomic_exchange_acq ((mem), (n)); \ + }) + +/* Various macros that should just be synonyms. */ +#define catomic_exchange_and_add atomic_exchange_and_add +#define atomic_and(mem, mask) ((void) atomic_and_val ((mem), (mask))) +#define catomic_and atomic_and +#define atomic_or(mem, mask) ((void) atomic_or_val ((mem), (mask))) +#define catomic_or atomic_or + +/* atomic_bit_test_set in terms of atomic_or_val. */ +#define atomic_bit_test_set(mem, bit) \ + ({ __typeof (*(mem)) __att0_mask = ((__typeof (*(mem))) 1 << (bit)); \ + atomic_or_val ((mem), __att0_mask) & __att0_mask; }) + +/* + * This non-existent symbol is called for unsupporrted sizes, + * indicating a bug in the caller. + */ +extern int __atomic_error_bad_argument_size(void) + __attribute__ ((warning ("bad sizeof atomic argument"))); diff --git a/sysdeps/tile/bits/byteswap.h b/sysdeps/tile/bits/byteswap.h new file mode 100644 index 0000000000..6858a3018d --- /dev/null +++ b/sysdeps/tile/bits/byteswap.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H && !defined _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* gcc __builtin_bswap64() can constant-fold, etc, so always use it. */ +#define __bswap_16(x) ((unsigned short)(__builtin_bswap32(x) >> 16)) +#define __bswap_32(x) ((unsigned int)__builtin_bswap32(x)) +#define __bswap_64(x) ((unsigned long long)__builtin_bswap64(x)) + +#define __bswap_constant_16(x) __bswap_16(x) +#define __bswap_constant_32(x) __bswap_32(x) +#define __bswap_constant_64(x) __bswap_64(x) + +#endif /* _BITS_BYTESWAP_H */ diff --git a/sysdeps/tile/bits/endian.h b/sysdeps/tile/bits/endian.h new file mode 100644 index 0000000000..43d94bb7a7 --- /dev/null +++ b/sysdeps/tile/bits/endian.h @@ -0,0 +1,13 @@ +/* Set endianness for tile. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#if defined __BIG_ENDIAN__ +# define __BYTE_ORDER __BIG_ENDIAN +#elif defined __LITTLE_ENDIAN__ +# define __BYTE_ORDER __LITTLE_ENDIAN +#else +# error "Endianness not declared!!" +#endif diff --git a/sysdeps/tile/bits/fenv.h b/sysdeps/tile/bits/fenv.h new file mode 100644 index 0000000000..56fe6fd911 --- /dev/null +++ b/sysdeps/tile/bits/fenv.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 _FENV_H +# error "Never use directly; include instead." +#endif + +/* The TILE-Gx hardware does not provide floating-point exception + handling, and TILEPro does not support any floating-point operations. */ +#define FE_ALL_EXCEPT 0 + +/* TILE-Gx supports only round-to-nearest. The software + floating-point support also acts this way. */ +enum + { + FE_TONEAREST = 1, +#define FE_TONEAREST FE_TONEAREST + }; + +/* Type representing exception flags (if there were any). */ +typedef unsigned int fexcept_t; + +/* Type representing floating-point environment. */ +typedef unsigned int fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1l) diff --git a/sysdeps/tile/bits/link.h b/sysdeps/tile/bits/link.h new file mode 100644 index 0000000000..f4b7462172 --- /dev/null +++ b/sysdeps/tile/bits/link.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 _LINK_H +# error "Never include directly; use instead." +#endif + +#define __need_int_reg_t +#include + + +/* Registers for entry into PLT. */ +typedef struct La_tile_regs +{ + __uint_reg_t lr_reg[10]; +} La_tile_regs; + +/* Return values for calls from PLT. */ +typedef struct La_tile_retval +{ + /* Up to ten registers can be used for a return value (e.g. small struct). */ + __uint_reg_t lrv_reg[10]; +} La_tile_retval; + + +__BEGIN_DECLS + +extern ElfW(Addr) la_tile_gnu_pltenter (ElfW(Sym) *__sym, unsigned int __ndx, + uintptr_t *__refcook, + uintptr_t *__defcook, + La_tile_regs *__regs, + unsigned int *__flags, + const char *__symname, + long int *__framesizep); +extern unsigned int la_tile_gnu_pltexit (ElfW(Sym) *__sym, unsigned int __ndx, + uintptr_t *__refcook, + uintptr_t *__defcook, + const La_tile_regs *__inregs, + La_tile_retval *__outregs, + const char *__symname); + +__END_DECLS diff --git a/sysdeps/tile/bits/mathdef.h b/sysdeps/tile/bits/mathdef.h new file mode 100644 index 0000000000..7c7ef5dd97 --- /dev/null +++ b/sysdeps/tile/bits/mathdef.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* "float" and "double" expressions evaluated as "float" and "double". */ +typedef float float_t; +typedef double double_t; + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +/* The GCC 4.6 compiler will define __FP_FAST_FMA{,F,L} if the fma{,f,l} + builtins are supported. */ +# if __FP_FAST_FMA +# define FP_FAST_FMA 1 +# endif + +# if __FP_FAST_FMAF +# define FP_FAST_FMAF 1 +# endif + +# if __FP_FAST_FMAL +# define FP_FAST_FMAL 1 +# endif + +#endif /* ISO C99 */ diff --git a/sysdeps/tile/bits/mathinline.h b/sysdeps/tile/bits/mathinline.h new file mode 100644 index 0000000000..09bdd79186 --- /dev/null +++ b/sysdeps/tile/bits/mathinline.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 _MATH_H +# error "Never use directly; include instead." +#endif + +#ifndef __extern_always_inline +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE __extern_always_inline +#endif + + +#if defined __USE_ISOC99 && defined __GNUC__ + +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + return __builtin_signbitf (__x); +} +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + return __builtin_signbit (__x); +} + +#endif diff --git a/sysdeps/tile/bits/setjmp.h b/sysdeps/tile/bits/setjmp.h new file mode 100644 index 0000000000..49612591ed --- /dev/null +++ b/sysdeps/tile/bits/setjmp.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 the machine-dependent type `jmp_buf'. TILE version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM + +#define __need_int_reg_t +#include + +typedef __uint_reg_t __jmp_buf[32]; + +#endif + +#endif /* bits/setjmp.h */ diff --git a/sysdeps/tile/bsd-_setjmp.S b/sysdeps/tile/bsd-_setjmp.S new file mode 100644 index 0000000000..4e6a2da560 --- /dev/null +++ b/sysdeps/tile/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp is in setjmp.S */ diff --git a/sysdeps/tile/bsd-setjmp.S b/sysdeps/tile/bsd-setjmp.S new file mode 100644 index 0000000000..1da848d2f1 --- /dev/null +++ b/sysdeps/tile/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp is in setjmp.S */ diff --git a/sysdeps/tile/bzero.S b/sysdeps/tile/bzero.S new file mode 100644 index 0000000000..5b5b9da235 --- /dev/null +++ b/sysdeps/tile/bzero.S @@ -0,0 +1,31 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__bzero) + FEEDBACK_ENTER(__bzero) + { + move r2, r1 + move r1, zero + } + j __memset +END(__bzero) +weak_alias (__bzero, bzero) diff --git a/sysdeps/tile/dl-lookupcfg.h b/sysdeps/tile/dl-lookupcfg.h new file mode 100644 index 0000000000..e1a5b26da9 --- /dev/null +++ b/sysdeps/tile/dl-lookupcfg.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 DL_UNMAP_IS_SPECIAL + +#include_next + +struct link_map; + +void internal_function _dl_unmap (struct link_map *map); + +#define DL_UNMAP(map) _dl_unmap (map) diff --git a/sysdeps/tile/dl-machine.h b/sysdeps/tile/dl-machine.h new file mode 100644 index 0000000000..8b3c534a94 --- /dev/null +++ b/sysdeps/tile/dl-machine.h @@ -0,0 +1,918 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + Based on work contributed by by Carl Pederson & Martin Schwidefsky. + + 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 dl_machine_h +#define dl_machine_h + +#ifdef __tilegx__ +#define ELF_MACHINE_NAME "tilegx" +#else +#define ELF_MACHINE_NAME "tilepro" +#endif + +#include +#include +#include +#include +#include +#include + +/* Return nonzero iff ELF header is compatible with the running host. */ +static inline int +elf_machine_matches_host (const ElfW(Ehdr) *ehdr) +{ +#if defined __tilegx__ + if (ehdr->e_machine != EM_TILEGX) + return 0; +# if __WORDSIZE == 32 + return (ehdr->e_ident[EI_CLASS] == ELFCLASS32); +# else + return (ehdr->e_ident[EI_CLASS] == ELFCLASS64); +# endif +#elif defined __tilepro__ + return ehdr->e_machine == EM_TILEPRO; +#else +# error "Unknown tile architecture." +#endif +} + + +/* 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 ElfW(Addr) +elf_machine_dynamic (void) +{ + ElfW(Addr) *got; + +#ifdef __tilegx__ + ElfW(Addr) tmp; + asm( " { lnk %0; moveli %1, hw2_last(_GLOBAL_OFFSET_TABLE_ - 1f) }\n" + "1: shl16insli %1, %1, hw1(_GLOBAL_OFFSET_TABLE_ - 1b)\n" + " shl16insli %1, %1, hw0(_GLOBAL_OFFSET_TABLE_ - 1b)\n" + " add %0, %0, %1" + : "=r" (got), "=r" (tmp)); +#else + asm( " lnk %0\n" + "1: addli %0, %0, lo16(_GLOBAL_OFFSET_TABLE_ - 1b)\n" + " auli %0, %0, ha16(_GLOBAL_OFFSET_TABLE_ - 1b)" + : "=r" (got)); +#endif + + return *got; +} + + +/* Return the run-time load address of the shared object. */ +static inline ElfW(Addr) +elf_machine_load_address (void) +{ + ElfW(Addr) *got; + ElfW(Addr) dynamic; + +#ifdef __tilegx__ + ElfW(Addr) tmp; + asm( " lnk %2\n" + "1: {\n" + " moveli %0, hw2_last(_GLOBAL_OFFSET_TABLE_ - 1b)\n" + " moveli %1, hw2_last(_DYNAMIC - 1b)\n" + " }\n" + " {\n" + " shl16insli %0, %0, hw1(_GLOBAL_OFFSET_TABLE_ - 1b)\n" + " shl16insli %1, %1, hw1(_DYNAMIC - 1b)\n" + " }\n" + " {\n" + " shl16insli %0, %0, hw0(_GLOBAL_OFFSET_TABLE_ - 1b)\n" + " shl16insli %1, %1, hw0(_DYNAMIC - 1b)\n" + " }\n" + " {\n" + " add %0, %0, %2\n" + " add %1, %1, %2\n" + " }" + : "=r" (got), "=r" (dynamic), "=r" (tmp)); +#else + asm( " lnk %0\n" + "1: {\n" + " addli %0, %0, lo16(_GLOBAL_OFFSET_TABLE_ - 1b)\n" + " addli %1, %0, lo16(_DYNAMIC - 1b)\n" + " }\n" + " {\n" + " auli %0, %0, ha16(_GLOBAL_OFFSET_TABLE_ - 1b)\n" + " auli %1, %1, ha16(_DYNAMIC - 1b)\n" + " }\n" + : "=r" (got), "=r" (dynamic)); +#endif + + return dynamic - *got; +} + +/* Flush some range of the instruction cache. If invoked prior to + actually setting dl_pagesize, we conservatively use 4KB, which + is the smallest page size we could plausibly be running with. */ +static inline void +_dl_flush_icache (const void *addr, unsigned long size) +{ + invalidate_icache (addr, size, GLRO(dl_pagesize) ? : 4096); +} + +/* Set up the loaded object described by L so its unrelocated PLT + entries will jump to the on-demand fixup code in dl-runtime.c. */ + +static inline int __attribute__ ((unused)) +elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) +{ + ElfW(Addr) *gotplt; + extern void _dl_runtime_resolve (ElfW(Word)); + extern void _dl_runtime_profile (ElfW(Word)); + + if (l->l_info[DT_JMPREL] && lazy) + { + gotplt = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]); + + /* The GOT entries for functions in the PLT have not yet been filled + in. Their initial contents will arrange when called to put in + registers an offset into the .rel.plt section, and gotplt[0], then + jump to gotplt[1]. */ + + /* Identify this shared object. */ + gotplt[0] = (ElfW(Addr)) l; + + /* The gotplt[1] entry contains the address of a function which gets + called to get the address of a so far unresolved function and jump + to it. The profiling extension of the dynamic linker allows to + intercept the calls to collect information. In this case we don't + store the address in the GOTPLT so that all future calls also end + in this function. */ + if (__builtin_expect (profile, 0)) + { + gotplt[1] = (ElfW(Addr)) &_dl_runtime_profile; + + if (GLRO(dl_profile) != NULL + && _dl_name_match_p (GLRO(dl_profile), l)) + /* This is the object we are looking for. Say that we really + want profiling and the timers are started. */ + GL(dl_profile_map) = l; + } + else + /* This function will get called to fix up the GOTPLT entry + indicated by the offset on the stack, and then jump to the + resolved address. */ + gotplt[1] = (ElfW(Addr)) &_dl_runtime_resolve; + } + + return lazy; +} + +#if __WORDSIZE == 32 +/* Mask identifying addresses reserved for the user program, + where the dynamic linker should not map anything. */ +#define ELF_MACHINE_USER_ADDRESS_MASK 0xf8000000UL +#endif + +/* Initial entry point code for the dynamic linker. + The C function `_dl_start' is the real entry point; + its return value is the user program's entry point. */ + +#define RTLD_START asm (".globl _dl_start"); + +#ifndef RTLD_START_SPECIAL_INIT +#define RTLD_START_SPECIAL_INIT /* nothing */ +#endif + +/* Wrap a generic Tilera relocation type. */ +#ifdef __tilegx__ +#define R_TILE(x) R_TILEGX_##x +#define __R_TILE_TLS(x,c) R_TILEGX_TLS_##x##c +#define _R_TILE_TLS(x,c) __R_TILE_TLS(x,c) +#define R_TILE_TLS(x) _R_TILE_TLS(x,__ELF_NATIVE_CLASS) +#else +#define R_TILE(x) R_TILEPRO_##x +#define R_TILE_TLS(x) R_TILEPRO_TLS_##x##32 +#endif + +/* 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_TILE(JMP_SLOT) || (type) == R_TILE_TLS(DTPMOD) \ + || (type) == R_TILE_TLS(DTPOFF) || (type) == R_TILE_TLS(TPOFF)) \ + * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_TILE(COPY)) * ELF_RTYPE_CLASS_COPY)) + +/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ +#define ELF_MACHINE_JMP_SLOT R_TILE(JMP_SLOT) + +/* TILE never uses Elf32_Rel relocations. */ +#define ELF_MACHINE_NO_REL 1 + +/* TILE overlaps DT_RELA and DT_PLTREL. */ +#define ELF_MACHINE_PLTREL_OVERLAP 1 + +/* We define an initialization functions. This is called very early in + _dl_sysdep_start. */ +#define DL_PLATFORM_INIT dl_platform_init () + +static inline void __attribute__ ((unused)) +dl_platform_init (void) +{ + if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0') + /* Avoid an empty string which would disturb us. */ + GLRO(dl_platform) = NULL; +} + +static inline ElfW(Addr) +elf_machine_fixup_plt (struct link_map *map, lookup_t t, + const ElfW(Rela) *reloc, + ElfW(Addr) *reloc_addr, ElfW(Addr) value) +{ + return *reloc_addr = value; +} + +/* Return the final value of a plt relocation. */ +static inline ElfW(Addr) +elf_machine_plt_value (struct link_map *map, const ElfW(Rela) *reloc, + ElfW(Addr) value) +{ + return value; +} + +/* Support notifying the simulator about new objects. */ +void internal_function _dl_arch_map_object (struct link_map *l); +#define _dl_arch_map_object _dl_arch_map_object + +/* Names of the architecture-specific auditing callback functions. */ +#define ARCH_LA_PLTENTER tile_gnu_pltenter +#define ARCH_LA_PLTEXIT tile_gnu_pltexit + +#endif /* !dl_machine_h */ + + +#ifdef RESOLVE_MAP + +struct reloc_howto +{ + /* Right shift operand by this number of bits. */ + unsigned char right_shift; + +#ifdef __tilegx__ + /* If nonzero, this is updating a code bundle. */ + unsigned char is_bundle_update; +#else + /* If nonzero, add 0x8000 to the value. */ + unsigned char add_0x8000; +#endif + + /* If nonzero, subtract the containing address from the address. */ + unsigned char is_pcrel; + + /* Size in bytes, or 0 if this table entry should be ignored. */ + unsigned char byte_size; +}; + +/* Relocation information. Cannot contain create_* function pointers + because then the table would not be position-independent. */ +static const struct reloc_howto howto[] = +{ +#ifdef __tilegx__ + +# if __WORDSIZE == 32 + /* The GX -m32 loader only handles 32-bit types, so it will be confused + by shifts larger than that. We convert them to just sign-extend; + they usually indicate a program bug or missed optimization, but we + have to handle them correctly anyway. */ +# define S32 31 +# define S48 31 +# else +# define S32 32 +# define S48 48 +# endif + + /* R_TILEGX_NONE */ { 0, 0, 0, 0 }, + /* R_TILEGX_64 */ { 0, 0, 0, 8 }, + /* R_TILEGX_32 */ { 0, 0, 0, 4 }, + /* R_TILEGX_16 */ { 0, 0, 0, 2 }, + /* R_TILEGX_8 */ { 0, 0, 0, 1 }, + /* R_TILEGX_64_PCREL */ { 0, 0, 1, 8 }, + /* R_TILEGX_32_PCREL */ { 0, 0, 1, 4 }, + /* R_TILEGX_16_PCREL */ { 0, 0, 1, 2 }, + /* R_TILEGX_8_PCREL */ { 0, 0, 1, 1 }, + /* R_TILEGX_HW0 */ { 0, 0, 0, 0 }, + /* R_TILEGX_HW1 */ { 16, 0, 0, 0 }, + /* R_TILEGX_HW2 */ { S32, 0, 0, 0 }, + /* R_TILEGX_HW3 */ { S48, 0, 0, 0 }, + /* R_TILEGX_HW0_LAST */ { 0, 0, 0, 0 }, + /* R_TILEGX_HW1_LAST */ { 16, 0, 0, 0 }, + /* R_TILEGX_HW2_LAST */ { S32, 0, 0, 0 }, + /* R_TILEGX_COPY */ { 0, 0, 0, 0 }, + /* R_TILEGX_GLOB_DAT */ { 0, 0, 0, 8 }, + /* R_TILEGX_JMP_SLOT */ { 0, 0, 0, 0 }, + /* R_TILEGX_RELATIVE */ { 0, 0, 0, 0 }, + /* R_TILEGX_BROFF_X1 */ { 3, 1, 1, 8 }, + /* R_TILEGX_JUMPOFF_X1 */ { 3, 1, 1, 8 }, + /* R_TILEGX_JUMPOFF_X1_PLT */ { 3, 1, 1, 8 }, + /* R_TILEGX_IMM8_X0 */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM8_Y0 */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM8_X1 */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM8_Y1 */ { 0, 1, 0, 8 }, + /* R_TILEGX_DEST_IMM8_X1 */ { 0, 1, 0, 8 }, + /* R_TILEGX_MT_IMM14_X1 */ { 0, 1, 0, 8 }, + /* R_TILEGX_MF_IMM14_X1 */ { 0, 1, 0, 8 }, + /* R_TILEGX_MMSTART_X0 */ { 0, 1, 0, 8 }, + /* R_TILEGX_MMEND_X0 */ { 0, 1, 0, 8 }, + /* R_TILEGX_SHAMT_X0 */ { 0, 1, 0, 8 }, + /* R_TILEGX_SHAMT_X1 */ { 0, 1, 0, 8 }, + /* R_TILEGX_SHAMT_Y0 */ { 0, 1, 0, 8 }, + /* R_TILEGX_SHAMT_Y1 */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW0 */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW0 */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW1 */ { 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW1 */ { 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW2 */ { S32, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW2 */ { S32, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW3 */ { S48, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW3 */ { S48, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW0_LAST */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW0_LAST */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW1_LAST */ { 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW1_LAST */ { 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW2_LAST */ { S32, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW2_LAST */ { S32, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW0_PCREL */ { 0, 1, 1, 8 }, + /* R_TILEGX_IMM16_X1_HW0_PCREL */ { 0, 1, 1, 8 }, + /* R_TILEGX_IMM16_X0_HW1_PCREL */ { 16, 1, 1, 8 }, + /* R_TILEGX_IMM16_X1_HW1_PCREL */ { 16, 1, 1, 8 }, + /* R_TILEGX_IMM16_X0_HW2_PCREL */ { S32, 1, 1, 8 }, + /* R_TILEGX_IMM16_X1_HW2_PCREL */ { S32, 1, 1, 8 }, + /* R_TILEGX_IMM16_X0_HW3_PCREL */ { S48, 1, 1, 8 }, + /* R_TILEGX_IMM16_X1_HW3_PCREL */ { S48, 1, 1, 8 }, + /* R_TILEGX_IMM16_X0_HW0_LAST_PCREL */ { 0, 1, 1, 8 }, + /* R_TILEGX_IMM16_X1_HW0_LAST_PCREL */ { 0, 1, 1, 8 }, + /* R_TILEGX_IMM16_X0_HW1_LAST_PCREL */ { 16, 1, 1, 8 }, + /* R_TILEGX_IMM16_X1_HW1_LAST_PCREL */ { 16, 1, 1, 8 }, + /* R_TILEGX_IMM16_X0_HW2_LAST_PCREL */ { S32, 1, 1, 8 }, + /* R_TILEGX_IMM16_X1_HW2_LAST_PCREL */ { S32, 1, 1, 8 }, + /* R_TILEGX_IMM16_X0_HW0_GOT */ { 0, 1, 0, 0 }, + /* R_TILEGX_IMM16_X1_HW0_GOT */ { 0, 1, 0, 0 }, + /* R_TILEGX_IMM16_X0_HW1_GOT */ { 16, 1, 0, 0 }, + /* R_TILEGX_IMM16_X1_HW1_GOT */ { 16, 1, 0, 0 }, + /* R_TILEGX_IMM16_X0_HW2_GOT */ { S32, 1, 0, 0 }, + /* R_TILEGX_IMM16_X1_HW2_GOT */ { S32, 1, 0, 0 }, + /* R_TILEGX_IMM16_X0_HW3_GOT */ { S48, 1, 0, 0 }, + /* R_TILEGX_IMM16_X1_HW3_GOT */ { S48, 1, 0, 0 }, + /* R_TILEGX_IMM16_X0_HW0_LAST_GOT */ { 0, 1, 0, 0 }, + /* R_TILEGX_IMM16_X1_HW0_LAST_GOT */ { 0, 1, 0, 0 }, + /* R_TILEGX_IMM16_X0_HW1_LAST_GOT */ { 16, 1, 0, 0 }, + /* R_TILEGX_IMM16_X1_HW1_LAST_GOT */ { 16, 1, 0, 0 }, + /* R_TILEGX_IMM16_X0_HW2_LAST_GOT */ { S32, 1, 0, 0 }, + /* R_TILEGX_IMM16_X1_HW2_LAST_GOT */ { S32, 1, 0, 0 }, + /* R_TILEGX_IMM16_X0_HW0_TLS_GD */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW0_TLS_GD */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW1_TLS_GD */ { 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW1_TLS_GD */ { 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW2_TLS_GD */ { S32, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW2_TLS_GD */ { S32, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW3_TLS_GD */ { S48, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW3_TLS_GD */ { S48, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD */{ 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD */{ 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD */{ 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD */{ 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW2_LAST_TLS_GD */{ S32, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW2_LAST_TLS_GD */{ S32, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW0_TLS_IE */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW0_TLS_IE */ { 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW1_TLS_IE */ { 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW1_TLS_IE */ { 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW2_TLS_IE */ { S32, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW2_TLS_IE */ { S32, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW3_TLS_IE */ { S48, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW3_TLS_IE */ { S48, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE */{ 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE */{ 0, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE */{ 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE */{ 16, 1, 0, 8 }, + /* R_TILEGX_IMM16_X0_HW2_LAST_TLS_IE */{ S32, 1, 0, 8 }, + /* R_TILEGX_IMM16_X1_HW2_LAST_TLS_IE */{ S32, 1, 0, 8 }, + /* R_TILEGX_TLS_DTPMOD64 */ { 0, 0, 0, 0 }, + /* R_TILEGX_TLS_DTPOFF64 */ { 0, 0, 0, 0 }, + /* R_TILEGX_TLS_TPOFF64 */ { 0, 0, 0, 0 }, + /* R_TILEGX_TLS_DTPMOD32 */ { 0, 0, 0, 0 }, + /* R_TILEGX_TLS_DTPOFF32 */ { 0, 0, 0, 0 }, + /* R_TILEGX_TLS_TPOFF32 */ { 0, 0, 0, 0 } +#else + /* R_TILEPRO_NONE */ { 0, 0, 0, 0 }, + /* R_TILEPRO_32 */ { 0, 0, 0, 4 }, + /* R_TILEPRO_16 */ { 0, 0, 0, 2 }, + /* R_TILEPRO_8 */ { 0, 0, 0, 1 }, + /* R_TILEPRO_32_PCREL */ { 0, 0, 1, 4 }, + /* R_TILEPRO_16_PCREL */ { 0, 0, 1, 2 }, + /* R_TILEPRO_8_PCREL */ { 0, 0, 1, 1 }, + /* R_TILEPRO_LO16 */ { 0, 0, 0, 2 }, + /* R_TILEPRO_HI16 */ { 16, 0, 0, 2 }, + /* R_TILEPRO_HA16 */ { 16, 1, 0, 2 }, + /* R_TILEPRO_COPY */ { 0, 0, 0, 0 }, + /* R_TILEPRO_GLOB_DAT */ { 0, 0, 0, 4 }, + /* R_TILEPRO_JMP_SLOT */ { 0, 0, 0, 0 }, + /* R_TILEPRO_RELATIVE */ { 0, 0, 0, 0 }, + /* R_TILEPRO_BROFF_X1 */ { 3, 0, 1, 8 }, + /* R_TILEPRO_JOFFLONG_X1 */ { 3, 0, 1, 8 }, + /* R_TILEPRO_JOFFLONG_X1_PLT */ { 3, 0, 1, 8 }, + /* R_TILEPRO_IMM8_X0 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM8_Y0 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM8_X1 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM8_Y1 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_MT_IMM15_X1 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_MF_IMM15_X1 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X0 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X1 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X0_LO */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X1_LO */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X0_HI */ { 16, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X1_HI */ { 16, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X0_HA */ { 16, 1, 0, 8 }, + /* R_TILEPRO_IMM16_X1_HA */ { 16, 1, 0, 8 }, + /* R_TILEPRO_IMM16_X0_PCREL */ { 0, 0, 1, 8 }, + /* R_TILEPRO_IMM16_X1_PCREL */ { 0, 0, 1, 8 }, + /* R_TILEPRO_IMM16_X0_LO_PCREL */ { 0, 0, 1, 8 }, + /* R_TILEPRO_IMM16_X1_LO_PCREL */ { 0, 0, 1, 8 }, + /* R_TILEPRO_IMM16_X0_HI_PCREL */ { 16, 0, 1, 8 }, + /* R_TILEPRO_IMM16_X1_HI_PCREL */ { 16, 0, 1, 8 }, + /* R_TILEPRO_IMM16_X0_HA_PCREL */ { 16, 1, 1, 8 }, + /* R_TILEPRO_IMM16_X1_HA_PCREL */ { 16, 1, 1, 8 }, + /* R_TILEPRO_IMM16_X0_GOT */ { 0, 0, 0, 0 }, + /* R_TILEPRO_IMM16_X1_GOT */ { 0, 0, 0, 0 }, + /* R_TILEPRO_IMM16_X0_GOT_LO */ { 0, 0, 0, 0 }, + /* R_TILEPRO_IMM16_X1_GOT_LO */ { 0, 0, 0, 0 }, + /* R_TILEPRO_IMM16_X0_GOT_HI */ { 0, 0, 0, 0 }, + /* R_TILEPRO_IMM16_X1_GOT_HI */ { 0, 0, 0, 0 }, + /* R_TILEPRO_IMM16_X0_GOT_HA */ { 0, 0, 0, 0 }, + /* R_TILEPRO_IMM16_X1_GOT_HA */ { 0, 0, 0, 0 }, + /* R_TILEPRO_MMSTART_X0 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_MMEND_X0 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_MMSTART_X1 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_MMEND_X1 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_SHAMT_X0 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_SHAMT_X1 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_SHAMT_Y0 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_SHAMT_Y1 */ { 0, 0, 0, 8 }, + /* R_TILEPRO_SN_BROFF */ { 0, 0, 0, 0 }, + /* R_TILEPRO_SN_IMM8 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_SN_UIMM8 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_SN_BYTE0 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_SN_BYTE1 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_SN_BYTE2 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_SN_BYTE3 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_SN_SPCREL0 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_SN_SPCREL1 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_SN_SPCREL2 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_SN_SPCREL3 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_IMM16_X0_TLS_GD */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X1_TLS_GD */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X0_TLS_GD_LO */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X1_TLS_GD_LO */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X0_TLS_GD_HI */ { 16, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X1_TLS_GD_HI */ { 16, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X0_TLS_GD_HA */ { 16, 1, 0, 8 }, + /* R_TILEPRO_IMM16_X1_TLS_GD_HA */ { 16, 1, 0, 8 }, + /* R_TILEPRO_IMM16_X0_TLS_IE */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X1_TLS_IE */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X0_TLS_IE_LO */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X1_TLS_IE_LO */ { 0, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X0_TLS_IE_HI */ { 16, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X1_TLS_IE_HI */ { 16, 0, 0, 8 }, + /* R_TILEPRO_IMM16_X0_TLS_IE_HA */ { 16, 1, 0, 8 }, + /* R_TILEPRO_IMM16_X1_TLS_IE_HA */ { 16, 1, 0, 8 }, + /* R_TILEPRO_TLS_DTPMOD32 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_TLS_DTPOFF32 */ { 0, 0, 0, 0 }, + /* R_TILEPRO_TLS_TPOFF32 */ { 0, 0, 0, 0 }, +#endif +}; + +#if __ELF_NATIVE_CLASS == 32 +#define ELFW_R_TYPE ELF32_R_TYPE +#define ELFW_ST_TYPE ELF32_ST_TYPE +#else +#define ELFW_R_TYPE ELF64_R_TYPE +#define ELFW_ST_TYPE ELF64_ST_TYPE +#endif + +/* Perform the relocation specified by RELOC and SYM (which is fully resolved). + MAP is the object containing the reloc. */ + +auto inline void __attribute__ ((always_inline)) +elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, + const ElfW(Sym) *sym, const struct r_found_version *version, + void *const reloc_addr_arg, int skip_ifunc) +{ + ElfW(Addr) *const reloc_addr = reloc_addr_arg; + const unsigned int r_type = ELFW_R_TYPE (reloc->r_info); + +#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC + if (__builtin_expect (r_type == R_TILE(RELATIVE), 0)) + { +# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC + /* This is defined in rtld.c, but nowhere in the static libc.a; + make the reference weak so static programs can still link. + This declaration cannot be done when compiling rtld.c + (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the + common defn for _dl_rtld_map, which is incompatible with a + weak decl in the same file. */ +# ifndef SHARED + weak_extern (GL(dl_rtld_map)); +# endif + if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ +# endif + *reloc_addr = map->l_addr + reloc->r_addend; + return; + } +#endif + + if (__builtin_expect (r_type == R_TILE(NONE), 0)) + return; + +#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP + const ElfW(Sym) *const refsym = sym; +#endif + struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); + ElfW(Addr) value; + + if (sym == NULL) + value = 0; + else if (ELFW_ST_TYPE (sym->st_info) == STT_SECTION) + value = map->l_addr; /* like a RELATIVE reloc */ + else + value = sym_map->l_addr + sym->st_value; + + if (sym != NULL + && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0) + && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1) + && __builtin_expect (!skip_ifunc, 1)) + value = ((Elf64_Addr (*) (void)) value) (); + + switch (r_type) + { + case R_TILE(JMP_SLOT): + elf_machine_fixup_plt (map, 0, reloc, reloc_addr, + value + reloc->r_addend); + return; + +#ifndef RESOLVE_CONFLICT_FIND_MAP + case R_TILE_TLS(DTPMOD): +# ifdef RTLD_BOOTSTRAP + /* During startup the dynamic linker is always the module + with index 1. + XXX If this relocation is necessary move before RESOLVE + call. */ + *reloc_addr = 1; +# else + /* Get the information from the link map returned by the + resolv function. */ + if (sym_map != NULL) + *reloc_addr = sym_map->l_tls_modid; +# endif + return; + case R_TILE_TLS(DTPOFF): +# ifndef RTLD_BOOTSTRAP + /* During relocation all TLS symbols are defined and used. + Therefore the offset is already correct. */ + if (sym != NULL) + *reloc_addr = sym->st_value + reloc->r_addend; +# endif + return; + case R_TILE_TLS(TPOFF): +# ifdef RTLD_BOOTSTRAP + *reloc_addr = sym->st_value + reloc->r_addend + map->l_tls_offset; +# else + if (sym != NULL) + { + CHECK_STATIC_TLS (map, sym_map); + *reloc_addr = (sym->st_value + reloc->r_addend + + sym_map->l_tls_offset); + } +#endif + return; +#endif /* use TLS */ + +#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP + /* Not needed in dl-conflict.c. */ + case R_TILE(COPY): + if (sym == NULL) + /* This can happen in trace mode if an object could not be found. */ + return; + if (__builtin_expect (sym->st_size > refsym->st_size, 0) + || (__builtin_expect (sym->st_size < refsym->st_size, 0) + && __builtin_expect (GLRO(dl_verbose), 0))) + { + const char *strtab; + + strtab = (const char *) D_PTR (map,l_info[DT_STRTAB]); + _dl_error_printf ("%s: Symbol `%s' has different size in shared" + " object, consider re-linking\n", + rtld_progname ?: "", + strtab + refsym->st_name); + } + memcpy (reloc_addr_arg, (void *) value, + MIN (sym->st_size, refsym->st_size)); + return; +#endif + } + + /* All remaining relocations must be in the lookup table. */ + const struct reloc_howto *h = &howto[r_type]; + if ((unsigned int) r_type >= sizeof howto / sizeof howto[0] || + h->byte_size == 0) + { +#if !defined RTLD_BOOTSTRAP || defined _NDEBUG + /* We add these checks in the version to relocate ld.so only + if we are still debugging. */ + _dl_reloc_bad_type (map, r_type, 0); +#endif + return; + } + + value += reloc->r_addend; + + /* The lookup table entry knows how to perform this reloc. */ + if (h->is_pcrel) + value -= (ElfW(Addr)) reloc_addr; + +#ifndef __tilegx__ + if (h->add_0x8000) + value += 0x8000; +#endif + + value >>= h->right_shift; + + switch (h->byte_size) + { + case 1: + *(char *) reloc_addr = value; + return; + case 2: + *(short *) reloc_addr = value; + return; + case 4: + *(int *) reloc_addr = value; + return; +#ifdef __tilegx__ + case 8: + if (!h->is_bundle_update) + { + *(ElfW(Addr) *) reloc_addr = value; + return; + } +#endif + } + + /* We are updating a bundle, so use the function pointer that + swizzles the operand bits into the right location. */ + + tile_bundle_bits *p = (tile_bundle_bits *) reloc_addr; + tile_bundle_bits bits = *p; + +#define MUNGE(func) do { \ + bits = ((bits & ~create_##func (-1)) | create_##func (value)); \ + if (get_##func (bits) != value) \ + _dl_signal_error (0, map->l_name, NULL, \ + "relocation value too large for " #func); \ + } while (0) + +#define MUNGE_NOCHECK(func) \ + bits = ((bits & ~create_##func (-1)) | create_##func (value)) + + switch (r_type) + { +#ifdef __tilegx__ + case R_TILEGX_BROFF_X1: + MUNGE (BrOff_X1); + break; + case R_TILEGX_JUMPOFF_X1: + case R_TILEGX_JUMPOFF_X1_PLT: + MUNGE (JumpOff_X1); + break; + case R_TILEGX_IMM8_X0: + MUNGE (Imm8_X0); + break; + case R_TILEGX_IMM8_Y0: + MUNGE (Imm8_Y0); + break; + case R_TILEGX_IMM8_X1: + MUNGE (Imm8_X1); + break; + case R_TILEGX_IMM8_Y1: + MUNGE (Imm8_Y1); + break; + case R_TILEGX_MT_IMM14_X1: + MUNGE (MT_Imm14_X1); + break; + case R_TILEGX_MF_IMM14_X1: + MUNGE (MF_Imm14_X1); + break; + case R_TILEGX_IMM16_X0_HW0: + case R_TILEGX_IMM16_X0_HW1: + case R_TILEGX_IMM16_X0_HW2: + case R_TILEGX_IMM16_X0_HW3: + case R_TILEGX_IMM16_X0_HW0_PCREL: + case R_TILEGX_IMM16_X0_HW1_PCREL: + case R_TILEGX_IMM16_X0_HW2_PCREL: + case R_TILEGX_IMM16_X0_HW3_PCREL: + case R_TILEGX_IMM16_X0_HW0_TLS_GD: + case R_TILEGX_IMM16_X0_HW0_TLS_IE: + MUNGE_NOCHECK (Imm16_X0); + break; + case R_TILEGX_IMM16_X0_HW0_LAST: + case R_TILEGX_IMM16_X0_HW1_LAST: + case R_TILEGX_IMM16_X0_HW2_LAST: + case R_TILEGX_IMM16_X0_HW0_LAST_PCREL: + case R_TILEGX_IMM16_X0_HW1_LAST_PCREL: + case R_TILEGX_IMM16_X0_HW2_LAST_PCREL: + case R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD: + case R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD: + case R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE: + case R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE: + MUNGE (Imm16_X0); + break; + case R_TILEGX_IMM16_X1_HW0: + case R_TILEGX_IMM16_X1_HW1: + case R_TILEGX_IMM16_X1_HW2: + case R_TILEGX_IMM16_X1_HW3: + case R_TILEGX_IMM16_X1_HW0_PCREL: + case R_TILEGX_IMM16_X1_HW1_PCREL: + case R_TILEGX_IMM16_X1_HW2_PCREL: + case R_TILEGX_IMM16_X1_HW3_PCREL: + case R_TILEGX_IMM16_X1_HW0_TLS_GD: + case R_TILEGX_IMM16_X1_HW0_TLS_IE: + MUNGE_NOCHECK (Imm16_X1); + break; + case R_TILEGX_IMM16_X1_HW0_LAST: + case R_TILEGX_IMM16_X1_HW1_LAST: + case R_TILEGX_IMM16_X1_HW2_LAST: + case R_TILEGX_IMM16_X1_HW0_LAST_PCREL: + case R_TILEGX_IMM16_X1_HW1_LAST_PCREL: + case R_TILEGX_IMM16_X1_HW2_LAST_PCREL: + case R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD: + case R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD: + case R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE: + case R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE: + MUNGE (Imm16_X1); + break; + case R_TILEGX_MMSTART_X0: + MUNGE (BFStart_X0); + break; + case R_TILEGX_MMEND_X0: + MUNGE (BFEnd_X0); + break; + case R_TILEGX_SHAMT_X0: + MUNGE (ShAmt_X0); + break; + case R_TILEGX_SHAMT_X1: + MUNGE (ShAmt_X1); + break; + case R_TILEGX_SHAMT_Y0: + MUNGE (ShAmt_Y0); + break; + case R_TILEGX_SHAMT_Y1: + MUNGE (ShAmt_Y1); + break; +#else + case R_TILEPRO_BROFF_X1: + MUNGE (BrOff_X1); + break; + case R_TILEPRO_JOFFLONG_X1: + case R_TILEPRO_JOFFLONG_X1_PLT: + MUNGE_NOCHECK (JOffLong_X1); /* holds full 32-bit value */ + break; + case R_TILEPRO_IMM8_X0: + MUNGE (Imm8_X0); + break; + case R_TILEPRO_IMM8_Y0: + MUNGE (Imm8_Y0); + break; + case R_TILEPRO_IMM8_X1: + MUNGE (Imm8_X1); + break; + case R_TILEPRO_IMM8_Y1: + MUNGE (Imm8_Y1); + break; + case R_TILEPRO_MT_IMM15_X1: + MUNGE (MT_Imm15_X1); + break; + case R_TILEPRO_MF_IMM15_X1: + MUNGE (MF_Imm15_X1); + break; + case R_TILEPRO_IMM16_X0_LO: + case R_TILEPRO_IMM16_X0_HI: + case R_TILEPRO_IMM16_X0_HA: + case R_TILEPRO_IMM16_X0_LO_PCREL: + case R_TILEPRO_IMM16_X0_HI_PCREL: + case R_TILEPRO_IMM16_X0_HA_PCREL: + case R_TILEPRO_IMM16_X0_TLS_GD_LO: + case R_TILEPRO_IMM16_X0_TLS_GD_HI: + case R_TILEPRO_IMM16_X0_TLS_GD_HA: + case R_TILEPRO_IMM16_X0_TLS_IE_LO: + case R_TILEPRO_IMM16_X0_TLS_IE_HI: + case R_TILEPRO_IMM16_X0_TLS_IE_HA: + MUNGE_NOCHECK (Imm16_X0); + break; + case R_TILEPRO_IMM16_X0: + case R_TILEPRO_IMM16_X0_PCREL: + case R_TILEPRO_IMM16_X0_TLS_GD: + case R_TILEPRO_IMM16_X0_TLS_IE: + MUNGE (Imm16_X0); + break; + case R_TILEPRO_IMM16_X1_LO: + case R_TILEPRO_IMM16_X1_HI: + case R_TILEPRO_IMM16_X1_HA: + case R_TILEPRO_IMM16_X1_LO_PCREL: + case R_TILEPRO_IMM16_X1_HI_PCREL: + case R_TILEPRO_IMM16_X1_HA_PCREL: + case R_TILEPRO_IMM16_X1_TLS_GD_LO: + case R_TILEPRO_IMM16_X1_TLS_GD_HI: + case R_TILEPRO_IMM16_X1_TLS_GD_HA: + case R_TILEPRO_IMM16_X1_TLS_IE_LO: + case R_TILEPRO_IMM16_X1_TLS_IE_HI: + case R_TILEPRO_IMM16_X1_TLS_IE_HA: + MUNGE_NOCHECK (Imm16_X1); + break; + case R_TILEPRO_IMM16_X1: + case R_TILEPRO_IMM16_X1_PCREL: + case R_TILEPRO_IMM16_X1_TLS_GD: + case R_TILEPRO_IMM16_X1_TLS_IE: + MUNGE (Imm16_X1); + break; + case R_TILEPRO_MMSTART_X0: + MUNGE (MMStart_X0); + break; + case R_TILEPRO_MMEND_X0: + MUNGE (MMEnd_X0); + break; + case R_TILEPRO_MMSTART_X1: + MUNGE (MMStart_X1); + break; + case R_TILEPRO_MMEND_X1: + MUNGE (MMEnd_X1); + break; + case R_TILEPRO_SHAMT_X0: + MUNGE (ShAmt_X0); + break; + case R_TILEPRO_SHAMT_X1: + MUNGE (ShAmt_X1); + break; + case R_TILEPRO_SHAMT_Y0: + MUNGE (ShAmt_Y0); + break; + case R_TILEPRO_SHAMT_Y1: + MUNGE (ShAmt_Y1); + break; +#endif + } +#undef MUNGE + *p = bits; + _dl_flush_icache (p, sizeof (*p)); +} + +auto inline void __attribute__ ((always_inline)) +elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, + void *const reloc_addr_arg) +{ + ElfW(Addr) *const reloc_addr = reloc_addr_arg; + *reloc_addr = l_addr + reloc->r_addend; +} + +auto inline void __attribute__ ((always_inline)) +elf_machine_lazy_rel (struct link_map *map, + ElfW(Addr) l_addr, const ElfW(Rela) *reloc, + int skip_ifunc) +{ + const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); + + /* Check for unexpected PLT reloc type. */ + if (__builtin_expect (r_type == R_TILE(JMP_SLOT), 1)) + { + *(ElfW(Addr) *) (l_addr + reloc->r_offset) += l_addr; + } + else + _dl_reloc_bad_type (map, r_type, 1); +} + +#endif /* RESOLVE_MAP */ diff --git a/sysdeps/tile/dl-runtime.c b/sysdeps/tile/dl-runtime.c new file mode 100644 index 0000000000..e8a8361e27 --- /dev/null +++ b/sysdeps/tile/dl-runtime.c @@ -0,0 +1,80 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +/* Like x86_64, we pass the index of the relocation and not its offset. + In _dl_profile_fixup and _dl_call_pltexit we also use the index. + Therefore it is wasteful to compute the offset in the trampoline + just to reverse the operation immediately afterwards. */ +#define reloc_offset reloc_arg * sizeof (PLTREL) +#define reloc_index reloc_arg + +#include + +#include +#include + +/* Support notifying the simulator about new objects. */ +void internal_function +_dl_arch_map_object (struct link_map *l) +{ + int shift; + +#define DLPUTC(c) __insn_mtspr(SPR_SIM_CONTROL, \ + (SIM_CONTROL_DLOPEN \ + | ((c) << _SIM_CONTROL_OPERATOR_BITS))) + + /* Write the library address in hex. */ + DLPUTC ('0'); + DLPUTC ('x'); + for (shift = (int) sizeof (unsigned long) * 8 - 4; shift >= 0; shift -= 4) + DLPUTC ("0123456789abcdef"[(l->l_map_start >> shift) & 0xF]); + DLPUTC (':'); + + /* Write the library path, including the terminating '\0'. */ + for (size_t i = 0;; i++) + { + DLPUTC (l->l_name[i]); + if (l->l_name[i] == '\0') + break; + } +#undef DLPUTC +} + +/* Support notifying the simulator about removed objects prior to munmap(). */ +void internal_function +_dl_unmap (struct link_map *l) +{ + int shift; + +#define DLPUTC(c) __insn_mtspr(SPR_SIM_CONTROL, \ + (SIM_CONTROL_DLCLOSE \ + | ((c) << _SIM_CONTROL_OPERATOR_BITS))) + + /* Write the library address in hex. */ + DLPUTC ('0'); + DLPUTC ('x'); + for (shift = (int) sizeof (unsigned long) * 8 - 4; shift >= 0; shift -= 4) + DLPUTC ("0123456789abcdef"[(l->l_map_start >> shift) & 0xF]); + DLPUTC ('\0'); +#undef DLPUTC + + __munmap ((void *) l->l_map_start, l->l_map_end - l->l_map_start); +} + +#define DL_UNMAP(map) _dl_unmap (map) diff --git a/sysdeps/tile/dl-start.S b/sysdeps/tile/dl-start.S new file mode 100644 index 0000000000..2991374285 --- /dev/null +++ b/sysdeps/tile/dl-start.S @@ -0,0 +1,114 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + /* Get address of "sym" in "reg" assuming r51 holds ".Llink". */ + .macro pic_addr reg, sym +#ifdef __tilegx__ + moveli \reg, hw1_last(\sym - .Llink) + shl16insli \reg, \reg, hw0(\sym - .Llink) + ADD_PTR \reg, r51, \reg +#else + ADDLI_PTR \reg, r51, lo16(\sym - .Llink) + auli \reg, \reg, ha16(\sym - .Llink) +#endif + .endm + + .text +ENTRY (_start) + /* Linux starts us with sp pointing at the conventional Elf layout, + but we need to allow two 'caller' words for our ABI convention. */ + { + move r52, sp + andi sp, sp, -8 + } + cfi_def_cfa_register (r52) + { + /* Point sp at base of ABI area; point r4 to the caller-sp word. */ + ADDI_PTR sp, sp, -(2 * REGSIZE) + ADDI_PTR r4, sp, -REGSIZE + } + { + /* Save zero for caller sp in our 'caller' save area, and make + sure lr has a zero value, to limit backtraces. */ + move lr, zero + ST r4, zero + } + { + move r0, r52 + jal _dl_start + } + /* Save returned start of user program address for later. */ + move r50, r0 + + /* See if we were invoked explicitly with the dynamic loader, + in which case we have to adjust the argument vector. */ + lnk r51; .Llink: + pic_addr r4, _dl_skip_args + LD4U r4, r4 + BEQZT r4, .Lno_skip + + /* Load the argc word at the initial sp and adjust it. + We basically jump "sp" up over the first few argv entries + and write "argc" a little higher up in memory, to be the + base of the new kernel-initialized stack area. */ + LD_PTR r0, r52 + { + sub r0, r0, r4 + SHL_PTR_ADD r52, r4, r52 + } + { + ST_PTR r52, r0 + SHL_PTR_ADD sp, r4, sp + } + +.Lno_skip: + /* Call_dl_init (_dl_loaded, argc, argv, envp). See elf/start.s + for the layout of memory here; r52 is pointing to "+0". */ + pic_addr r0, _rtld_local + { + LD_PTR r1, r52 /* load argc in r1 */ + ADDLI_PTR r2, r52, __SIZEOF_POINTER__ /* point r2 at argv */ + } + { + LD_PTR r0, r0 /* yields _rtld_global._ns_loaded */ + addi r3, r1, 1 + move lr, zero + } + { + SHL_PTR_ADD r3, r3, r2 /* point r3 at envp */ + jal _dl_init_internal + } + + /* Call user program whose address we saved in r50. + We invoke it just like a static binary, but with _dl_fini + in r0 so we can distinguish. */ + + pic_addr r0, _dl_fini + move lr, zero + { + move sp, r52 + jr r50 + } + + /* Tell backtracer to give up (_start has no caller). */ + info 2 /* INFO_OP_CANNOT_BACKTRACE */ + +END (_start) diff --git a/sysdeps/tile/dl-tls.c b/sysdeps/tile/dl-tls.c new file mode 100644 index 0000000000..096539b4a7 --- /dev/null +++ b/sysdeps/tile/dl-tls.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +#ifdef SHARED +/* We provide a fast-path version of __tls_get_addr to allow for + the normal case to be fast, both by coding the function tightly, + and more importantly by fixing its register clobber API so the + compiler can avoid having to set up frames, etc., unnecessarily. */ +#define __tls_get_addr __tls_get_addr_slow +#endif + +#include diff --git a/sysdeps/tile/dl-tls.h b/sysdeps/tile/dl-tls.h new file mode 100644 index 0000000000..baa0c12686 --- /dev/null +++ b/sysdeps/tile/dl-tls.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + +/* Fast-path function to get a TLS pointer. */ +extern void *__tls_get_addr (tls_index *ti); + +/* The thread pointer points to the first static TLS block. */ +#define TLS_TP_OFFSET 0 + +/* Dynamic thread vector pointers at the start of each TLS block. */ +#define TLS_DTV_OFFSET 0 + +/* Compute the value for a GOTTPREL reloc. */ +#define TLS_TPREL_VALUE(sym_map, sym) \ + ((sym_map)->l_tls_offset + (sym)->st_value - TLS_TP_OFFSET) + +/* Compute the value for a DTPREL reloc. */ +#define TLS_DTPREL_VALUE(sym) \ + ((sym)->st_value - TLS_DTV_OFFSET) + +/* Value used for dtv entries for which the allocation is delayed. */ +#define TLS_DTV_UNALLOCATED ((void *) -1l) diff --git a/sysdeps/tile/dl-trampoline.S b/sysdeps/tile/dl-trampoline.S new file mode 100644 index 0000000000..486b958ed5 --- /dev/null +++ b/sysdeps/tile/dl-trampoline.S @@ -0,0 +1,194 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* This function is called via the PLT header, which is called + from an individual PLT entry. + + At this point we have several values passed in: + + lr: return address to original user code + r28: the tpnt value to pass to _dl_runtime_resolver + r29: the PLT index of the invoked jump table entry. + + We set up a frame entry that looks like this (in int_reg_t units): + + +57: r25 return values from function... + +56: r24 + [...] + +33: r1 + +32: r0 + +31: PLT index + +30: tpnt + +29: stackframe + +28: caller lr + +27: r25 arguments to function... + +26: r24 + [...] + +3: r1 + +2: r0 + +1: standard ABI slot (sp) + +0: standard ABI slot (callee lr) + + The entries from "stackframe" up are only used in _dl_profile_resolve. + We save and restore r0 through r25, rather than the strictly + architected r0 through r9, to support unusual calling conventions; + for example, __tls_get_addr takes r0 and returns r0, but promises + not to clobber r1 through r24 to support its usual fast path. */ + +#define FRAME_SP (1 * REGSIZE) +#define FRAME_REGS (2 * REGSIZE) +#define FRAME_LR (28 * REGSIZE) /* Must follow FRAME_REGS */ +#define FRAME_STACKFRAME (29 * REGSIZE) +#define FRAME_TPNT (30 * REGSIZE) +#define FRAME_INDEX (31 * REGSIZE) +#define FRAME_RETVAL (32 * REGSIZE) + +#define FRAME_SIZE_SMALL (30 * REGSIZE) +#define FRAME_SIZE_LARGE (58 * REGSIZE) + +#define FOR_EACH_REG(f) \ + f(r0); f(r1); f(r2); f(r3); \ + f(r4); f(r5); f(r6); f(r7); \ + f(r8); f(r9); f(r10); f(r11); \ + f(r12); f(r13); f(r14); f(r15); \ + f(r16); f(r17); f(r18); f(r19); \ + f(r20); f(r21); f(r22); f(r23); \ + f(r24); f(r25) + +#define SAVE(REG) { ST r27, REG; ADDI_PTR r27, r27, REGSIZE } +#define RESTORE(REG) { LD REG, r27; ADDI_PTR r27, r27, REGSIZE } + + .macro dl_resolve, name, profile, framesize +.text +.global \name +.hidden \name +/* Note that cpp expands ENTRY(\name) incorrectly. */ +.type \name,@function +.align 8 +\name: + cfi_startproc + { + ST sp, lr + move r26, sp + } + { + ADDLI_PTR sp, sp, -\framesize + ADDLI_PTR r27, sp, FRAME_SP - \framesize + } + cfi_def_cfa_offset (\framesize) + { + ST r27, r26 + ADDI_PTR r27, r27, FRAME_REGS - FRAME_SP + } + FOR_EACH_REG(SAVE) + { + ST r27, lr + ADDLI_PTR r27, sp, FRAME_TPNT + } + cfi_offset (lr, FRAME_LR - \framesize) + .if \profile + { + move r0, r28 /* tpnt value */ + ST r27, r28 + ADDI_PTR r27, r27, FRAME_INDEX - FRAME_TPNT + } + { + move r1, r29 /* PLT index */ + ST r27, r29 + } + { + move r2, lr /* retaddr */ + ADDI_PTR r3, sp, FRAME_REGS /* La_tile_regs pointer */ + } + { + ADDLI_PTR r4, sp, FRAME_STACKFRAME /* framesize pointer */ + jal _dl_profile_fixup + } + ADDLI_PTR r28, sp, FRAME_STACKFRAME + LD_PTR r28, r28 + BGTZ r28, 1f + .else + { + move r0, r28 /* tpnt value 1 */ + move r1, r29 /* PLT index 2 */ + } + jal _dl_fixup + .endif + { + /* Copy aside the return value so we can restore r0 below. */ + move r29, r0 + /* Set up r27 to let us start restoring registers. */ + ADDLI_PTR r27, sp, FRAME_REGS + } + FOR_EACH_REG(RESTORE) + .if \profile + ADDLI_PTR r28, sp, FRAME_STACKFRAME + LD r28, r28 + BGTZ r28, 1f + .endif + { + /* Restore original user return address. */ + LD lr, r27 + /* Pop off our stack frame. */ + ADDLI_PTR sp, sp, \framesize + } + cfi_def_cfa_offset (0) + jr r29 /* Transfer control to freshly loaded code. */ + jrp lr /* Keep backtracer happy. */ + + .if \profile +1: jalr r29 /* Call resolved function. */ + { + ADDLI_PTR r28, sp, FRAME_TPNT + ADDLI_PTR r27, sp, FRAME_RETVAL + } + FOR_EACH_REG(SAVE) + { + LD r0, r28 + ADDI_PTR r28, r28, FRAME_INDEX - FRAME_TPNT + } + { + LD r1, r28 + ADDLI_PTR r2, sp, FRAME_REGS + } + { + ADDLI_PTR r3, sp, FRAME_RETVAL + jal _dl_call_pltexit + } + { + ADDLI_PTR lr, sp, FRAME_LR + ADDLI_PTR r27, sp, FRAME_RETVAL + } + FOR_EACH_REG(RESTORE) + { + LD lr, lr + ADDLI_PTR sp, sp, \framesize + } + jrp lr + .endif +END (\name) + .endm + + dl_resolve _dl_runtime_resolve, 0, FRAME_SIZE_SMALL +#ifndef PROF + dl_resolve _dl_runtime_profile, 1, FRAME_SIZE_LARGE +#endif diff --git a/sysdeps/tile/elf/start.S b/sysdeps/tile/elf/start.S new file mode 100644 index 0000000000..71a2c8bc1f --- /dev/null +++ b/sysdeps/tile/elf/start.S @@ -0,0 +1,184 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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. */ + +/* This is the canonical entry point, usually the first thing in the text + segment. The ELF standard tells us that the stack is set up like this on + entry (the left side is the offset from "sp"), in units of + __SIZEOF_POINTER__ entries: + + +0 argc + +1 argv[0] + ... + +(argc+1) NULL + +(argc+2) envp[0] + ... + NULL + ... ElfInfo + + The ElfInfo is pairs of key/value long words following the envp + pointers and terminated by a zero-valued key. + + Although not mandated by the standard, it happens to be the case + that we store the actual argv and envp strings immediately after + the ElfInfo data on the stack. + + On entry r0 points to the shared library termination function, or 0 + if there isn't one. +*/ + +#include +#include +#include + + .text + .global _start + .type _start,@function + .align 8 +_start: + /* Linux starts us with sp pointing at the conventional Elf layout, + but we need to allow two "caller" words for our ABI convention. */ + { + /* Load argc (stored as a "long", equivalent to a pointer type). */ + LD_PTR r1, sp + + /* Save incoming 'sp', which points to the Elf argument block. */ + move r52, sp + } + + { + /* Allocate stack frame callee space for __libc_start_main. */ + ADDI_PTR r12, sp, -(2 * REGSIZE) + } + + { + /* Get our PC. */ + lnk r13 + + /* sp is not necessarily properly aligned on startup because + of the way ld.so pops off leading argv elements. So align it. */ + andi sp, r12, -8 + } +.Lmy_pc: + + { + /* Pass the address of the shared library termination function. */ + move r5, r0 + + /* Compute location where __libc_start_main's caller is supposed to + store its frame pointer. */ + ADDI_PTR r12, sp, REGSIZE + + /* Zero out callee space for return address. Unnecessary but free. + This is just paranoia to help backtracing not go awry. */ + ST sp, zero + } + { + /* Zero out our frame pointer for __libc_start_main. */ + ST r12, zero + + /* Zero out lr to make __libc_start_main the end of backtrace. */ + move lr, zero + + /* Compute a pointer to argv. envp will be determined + later in __libc_start_main. We set up the first argument + (the address of main) below. */ + ADDI_PTR r2, r52, __SIZEOF_POINTER__ + } + { + /* Pass the highest stack address to user code. */ + ADDI_PTR r6, sp, (2 * REGSIZE) + + /* Pass address of main() in r0, and of our own entry + points to .fini and .init in r3 and r4. */ +#ifdef __tilegx__ + moveli r0, hw2_last(main - .Lmy_pc) + } + { + moveli r3, hw2_last(__libc_csu_init - .Lmy_pc) + shl16insli r0, r0, hw1(main - .Lmy_pc) + } + { + shl16insli r3, r3, hw1(__libc_csu_init - .Lmy_pc) + shl16insli r0, r0, hw0(main - .Lmy_pc) + } + { + shl16insli r3, r3, hw0(__libc_csu_init - .Lmy_pc) + moveli r4, hw2_last(__libc_csu_fini - .Lmy_pc) + } + { + ADD_PTR r0, r0, r13 + shl16insli r4, r4, hw1(__libc_csu_fini - .Lmy_pc) + } + { + ADD_PTR r3, r3, r13 + shl16insli r4, r4, hw0(__libc_csu_fini - .Lmy_pc) + } + { + ADD_PTR r4, r4, r13 +#else + addli r0, r13, lo16(main - .Lmy_pc) + } + { + auli r0, r0, ha16(main - .Lmy_pc) + addli r3, r13, lo16(__libc_csu_init - .Lmy_pc) + } + { + auli r3, r3, ha16(__libc_csu_init - .Lmy_pc) + addli r4, r13, lo16(__libc_csu_fini - .Lmy_pc) + } + { + auli r4, r4, ha16(__libc_csu_fini - .Lmy_pc) + +#endif + + /* Call the user's main function, and exit with its value. + But let the libc call main. */ + j plt(__libc_start_main) + } + { + /* Tell backtracer to give up (_start has no caller). */ + info INFO_OP_CANNOT_BACKTRACE + } +.size _start, .-_start + +/* Define a symbol for the first piece of initialized data. */ + .data + .global __data_start + .align 8 +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/sysdeps/tile/fegetenv.c b/sysdeps/tile/fegetenv.c new file mode 100644 index 0000000000..f6e2bb173a --- /dev/null +++ b/sysdeps/tile/fegetenv.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +__fegetenv (fenv_t *envp) +{ + /* As a no-op, this always succeeds. */ + return 0; +} +libm_hidden_ver (__fegetenv, fegetenv) diff --git a/sysdeps/tile/fegetround.c b/sysdeps/tile/fegetround.c new file mode 100644 index 0000000000..f1217bf819 --- /dev/null +++ b/sysdeps/tile/fegetround.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetround (void) +{ + return FE_TONEAREST; +} diff --git a/sysdeps/tile/feholdexcpt.c b/sysdeps/tile/feholdexcpt.c new file mode 100644 index 0000000000..384b696abd --- /dev/null +++ b/sysdeps/tile/feholdexcpt.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Tile has no exception flags, so this routine can be a no-op. */ +int +feholdexcept (fenv_t *envp) +{ + return 0; +} +libm_hidden_def (feholdexcept) diff --git a/sysdeps/tile/fesetenv.c b/sysdeps/tile/fesetenv.c new file mode 100644 index 0000000000..ceb45e4d4d --- /dev/null +++ b/sysdeps/tile/fesetenv.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* The only way to get an initialized fenv_t on Tile is with feholdexcept() + or via FE_DFL_ENV, either of which restores the environment to its + normal state, i.e. FE_DFL_ENV. */ +int +__fesetenv (const fenv_t *envp) +{ + return 0; +} +libm_hidden_ver (__fesetenv, fesetenv) +versioned_symbol (libm, __fesetenv, fesetenv, GLIBC_2_2); diff --git a/sysdeps/tile/fesetround.c b/sysdeps/tile/fesetround.c new file mode 100644 index 0000000000..b29ecea915 --- /dev/null +++ b/sysdeps/tile/fesetround.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fesetround (int round) +{ + return (round == FE_TONEAREST) ? 0 : 1; +} +libm_hidden_def (fesetround) diff --git a/sysdeps/tile/feupdateenv.c b/sysdeps/tile/feupdateenv.c new file mode 100644 index 0000000000..5b021933e2 --- /dev/null +++ b/sysdeps/tile/feupdateenv.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Tile has no exception flags, so this routine can be a no-op. */ +int +feupdateenv (const fenv_t *envp) +{ + return 0; +} +libm_hidden_def (feupdateenv) diff --git a/sysdeps/tile/ffs.c b/sysdeps/tile/ffs.c new file mode 100644 index 0000000000..498559ca84 --- /dev/null +++ b/sysdeps/tile/ffs.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define ffsl __something_else +#include + +#undef ffs +int +__ffs (int x) +{ + return __builtin_ffs (x); +} +weak_alias (__ffs, ffs) +libc_hidden_builtin_def (ffs) + +#undef ffsll +int +ffsll (long long x) +{ + return __builtin_ffsll (x); +} + +#undef ffsl +#if ULONG_MAX == UINT_MAX +weak_alias (__ffs, ffsl) +#else +weak_alias (ffsll, ffsl) +#endif diff --git a/sysdeps/tile/ffsll.c b/sysdeps/tile/ffsll.c new file mode 100644 index 0000000000..180eaa8c23 --- /dev/null +++ b/sysdeps/tile/ffsll.c @@ -0,0 +1 @@ +/* This function is defined in ffs.c. */ diff --git a/sysdeps/tile/gccframe.h b/sysdeps/tile/gccframe.h new file mode 100644 index 0000000000..041d3d87a5 --- /dev/null +++ b/sysdeps/tile/gccframe.h @@ -0,0 +1,22 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 FIRST_PSEUDO_REGISTER 64 + +#include diff --git a/sysdeps/tile/jmpbuf-offsets.h b/sysdeps/tile/jmpbuf-offsets.h new file mode 100644 index 0000000000..ce4f1b2daa --- /dev/null +++ b/sysdeps/tile/jmpbuf-offsets.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +/* We don't use most of these symbols; they are here for documentation. */ +#define JB_R30 0 +#define JB_R31 1 +#define JB_R32 2 +#define JB_R33 3 +#define JB_R34 4 +#define JB_R35 5 +#define JB_R36 6 +#define JB_R37 7 +#define JB_R38 8 +#define JB_R39 9 +#define JB_R40 10 +#define JB_R41 11 +#define JB_R42 12 +#define JB_R43 13 +#define JB_R44 14 +#define JB_R45 15 +#define JB_R46 16 +#define JB_R47 17 +#define JB_R48 18 +#define JB_R49 19 +#define JB_R50 20 +#define JB_R51 21 +#define JB_FP 22 /* r52 */ +#define JB_TP 23 /* r53 */ +#define JB_SP 24 /* r54 */ +#define JB_PC 25 /* normally LR, r55 */ +#define JB_ICS 26 /* interrupt critical section bit */ + +/* We save space for some extra state to accomodate future changes. */ +#define JB_LEN 32 /* number of words */ + +#define JB_SIZE (JB_LEN * REGSIZE) + +/* Helper macro used by all the setjmp/longjmp assembly code. */ +#define FOR_EACH_CALLEE_SAVED_REG(f) \ + .no_require_canonical_reg_names; f(r30); f(r31); \ + f(r32); f(r33); f(r34); f(r35); f(r36); f(r37); f(r38); f(r39); \ + f(r40); f(r41); f(r42); f(r43); f(r44); f(r45); f(r46); f(r47); \ + f(r48); f(r49); f(r50); f(r51); f(r52); f(r53); f(r54); f(r55) + +/* Helper for generic ____longjmp_chk(). */ +#define JB_FRAME_ADDRESS(buf) \ + ((void *) (unsigned long) (buf[JB_SP])) diff --git a/sysdeps/tile/jmpbuf-unwind.h b/sysdeps/tile/jmpbuf-unwind.h new file mode 100644 index 0000000000..624a014868 --- /dev/null +++ b/sysdeps/tile/jmpbuf-unwind.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + Based on work contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +/* 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)[JB_SP])) + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +static inline uintptr_t __attribute__ ((unused)) +_jmpbuf_sp (__jmp_buf regs) +{ + uintptr_t sp = regs[JB_SP]; +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (sp); +#endif + return sp; +} + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj)) + +/* We use the normal longjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/sysdeps/tile/ldsodefs.h b/sysdeps/tile/ldsodefs.h new file mode 100644 index 0000000000..e90de56c0c --- /dev/null +++ b/sysdeps/tile/ldsodefs.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 _TILE_LDSODEFS_H +#define _TILE_LDSODEFS_H 1 + +#include + +struct La_tile_regs; +struct La_tile_retval; + +#define ARCH_PLTENTER_MEMBERS \ + ElfW(Addr) (*tile_gnu_pltenter) (ElfW(Sym) *, unsigned int, uintptr_t *, \ + uintptr_t *, struct La_tile_regs *, \ + unsigned int *, const char *, \ + long int *) + +#define ARCH_PLTEXIT_MEMBERS \ + ElfW(Addr) (*tile_gnu_pltexit) (ElfW(Sym) *, unsigned int, uintptr_t *, \ + uintptr_t *, struct La_tile_regs *, \ + struct La_tile_retval *, const char *) + +#include_next + +#endif diff --git a/sysdeps/tile/machine-gmon.h b/sysdeps/tile/machine-gmon.h new file mode 100644 index 0000000000..473707b037 --- /dev/null +++ b/sysdeps/tile/machine-gmon.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 _MCOUNT_DECL(from, self) \ + void __mcount_internal (u_long from, u_long self) + +/* Call __mcount_internal with our the return PC for our caller, and + the return PC our caller will return to. Empty since we use an + assembly stub instead. */ +#define MCOUNT diff --git a/sysdeps/tile/nptl/Makefile b/sysdeps/tile/nptl/Makefile new file mode 100644 index 0000000000..24990a2b7e --- /dev/null +++ b/sysdeps/tile/nptl/Makefile @@ -0,0 +1,21 @@ +# Copyright (C) 2002, 2003 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. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/sysdeps/tile/nptl/pthread_spin_lock.c b/sysdeps/tile/nptl/pthread_spin_lock.c new file mode 100644 index 0000000000..ee055623a5 --- /dev/null +++ b/sysdeps/tile/nptl/pthread_spin_lock.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include +#include + +/* Bound point for bounded exponential backoff */ +#define BACKOFF_MAX 2048 + +/* Initial cycle delay for exponential backoff */ +#define BACKOFF_START 32 + +#ifdef __tilegx__ +/* Use cmpexch() after the initial fast-path exch to avoid + invalidating the cache line of the lock holder. */ +# define TNS(p) atomic_exchange_acq((p), 1) +# define CMPTNS(p) atomic_compare_and_exchange_val_acq((p), 1, 0) +#else +# define TNS(p) __insn_tns(p) +# define CMPTNS(p) __insn_tns(p) +# define SPR_CYCLE SPR_CYCLE_LOW /* The low 32 bits are sufficient. */ +#endif + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ + if (__builtin_expect (TNS (lock) != 0, 0)) + { + unsigned int backoff = BACKOFF_START; + while (CMPTNS (lock) != 0) + { + unsigned int start = __insn_mfspr (SPR_CYCLE); + while (__insn_mfspr (SPR_CYCLE) - start < backoff) + ; + if (backoff < BACKOFF_MAX) + backoff *= 2; + } + } + return 0; +} diff --git a/sysdeps/tile/nptl/pthread_spin_trylock.c b/sysdeps/tile/nptl/pthread_spin_trylock.c new file mode 100644 index 0000000000..f111cc7c24 --- /dev/null +++ b/sysdeps/tile/nptl/pthread_spin_trylock.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + +#ifdef __tilegx__ +#define TNS(p) __insn_exch4((p), 1) +#else +#define TNS(p) __insn_tns(p) +#endif + +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return (TNS (lock) == 0) ? 0 : EBUSY; +} diff --git a/sysdeps/tile/nptl/pthreaddef.h b/sysdeps/tile/nptl/pthreaddef.h new file mode 100644 index 0000000000..4ba1adb0fa --- /dev/null +++ b/sysdeps/tile/nptl/pthreaddef.h @@ -0,0 +1,42 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + +/* XXX Until we have a better place keep the definitions here. */ + +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/sysdeps/tile/nptl/tcb-offsets.sym b/sysdeps/tile/nptl/tcb-offsets.sym new file mode 100644 index 0000000000..6740bc976f --- /dev/null +++ b/sysdeps/tile/nptl/tcb-offsets.sym @@ -0,0 +1,17 @@ +#define SHARED /* needed to get struct rtld_global from */ +#include +#include +#include + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. +#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + +MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) +PID_OFFSET thread_offsetof (pid) +TID_OFFSET thread_offsetof (tid) +POINTER_GUARD (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +FEEDBACK_DATA_OFFSET (offsetof (tcbhead_t, feedback_data) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +DTV_OFFSET (offsetof (tcbhead_t, dtv) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +TLS_GENERATION_OFFSET offsetof (struct rtld_global, _dl_tls_generation) diff --git a/sysdeps/tile/nptl/tls.h b/sysdeps/tile/nptl/tls.h new file mode 100644 index 0000000000..106451aa7a --- /dev/null +++ b/sysdeps/tile/nptl/tls.h @@ -0,0 +1,195 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 _TLS_H +#define _TLS_H 1 + +# include + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* We use the multiple_threads field in the pthread struct */ +#define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. */ +# include + +/* The stack_guard is accessed directly by GCC -fstack-protector code, + so it is a part of public ABI. The dtv and pointer_guard fields + are private. */ +typedef struct +{ + void *feedback_data; + uintptr_t pointer_guard; + uintptr_t stack_guard; + dtv_t *dtv; +} tcbhead_t; + +/* This is the size of the initial TCB. Because our TCB is before the thread + pointer, we don't need this. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. Because our TCB is before the thread + pointer, we don't need this. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size we need before TCB - actually, it includes the TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +/* Return the thread descriptor (tp) for the current thread. */ +register void *__thread_pointer asm ("tp"); + +/* The thread pointer (in hardware register tp) points to the end of + the TCB. The pthread_descr structure is immediately in front of the TCB. */ +# define TLS_TCB_OFFSET 0 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) (((tcbhead_t *) (tcbp))[-1].dtv) + +/* Code to initially initialize the thread pointer (tp). */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__thread_pointer = (char *)(tcbp) + TLS_TCB_OFFSET, NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) (__thread_pointer - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *) (__thread_pointer \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +#ifdef __tilegx__ +# define DB_THREAD_SELF \ + REGISTER (64, 64, REG_TP * 8, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) +#else +# define DB_THREAD_SELF \ + REGISTER (32, 32, REG_TP * 4, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) +#endif + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) (descr->member) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) \ + (descr->member[idx]) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ + (descr->member = (value)) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + (descr->member[idx] = (value)) + +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + (((tcbhead_t *) ((char *) __thread_pointer \ + - TLS_TCB_OFFSET))[-1].stack_guard = (value)) +# define THREAD_COPY_STACK_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].stack_guard \ + = ((tcbhead_t *) ((char *) __thread_pointer \ + - TLS_TCB_OFFSET))[-1].stack_guard) + +/* Set the pointer guard field in TCB head. */ +# define THREAD_GET_POINTER_GUARD() \ + (((tcbhead_t *) ((char *) __thread_pointer \ + - TLS_TCB_OFFSET))[-1].pointer_guard) +# define THREAD_SET_POINTER_GUARD(value) \ + (THREAD_GET_POINTER_GUARD () = (value)) +# define THREAD_COPY_POINTER_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].pointer_guard \ + = THREAD_GET_POINTER_GUARD()) + +/* l_tls_offset == 0 is perfectly valid on Tile, so we have to use some + different value to mean unset l_tls_offset. */ +# define NO_TLS_OFFSET -1 + +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/sysdeps/tile/preconfigure b/sysdeps/tile/preconfigure new file mode 100644 index 0000000000..9dba5b1040 --- /dev/null +++ b/sysdeps/tile/preconfigure @@ -0,0 +1,17 @@ +# This is a -*- sh -*- +case "$machine" in + tilepro) + base_machine=tile machine=tile/tilepro ;; + tilegx) + base_machine=tile + if $CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | grep -q __LP64__; then + machine=tile/tilegx/tilegx64 + else + machine=tile/tilegx/tilegx32 + fi ;; +esac +case "$machine" in + tile*) + libc_commonpagesize=0x10000 + libc_relro_required=yes ;; +esac diff --git a/sysdeps/tile/s_fma.c b/sysdeps/tile/s_fma.c new file mode 100644 index 0000000000..355b4edf6a --- /dev/null +++ b/sysdeps/tile/s_fma.c @@ -0,0 +1,3 @@ +/* Although tile uses ieee754/dbl-64, it does not support the + rounding modes required to use the standard dbl-64 s_fma.c. */ +#include diff --git a/sysdeps/tile/s_fmaf.c b/sysdeps/tile/s_fmaf.c new file mode 100644 index 0000000000..caa8e40654 --- /dev/null +++ b/sysdeps/tile/s_fmaf.c @@ -0,0 +1,3 @@ +/* Although tile uses ieee754/dbl-64, it does not support the + rounding modes required to use the standard dbl-64 s_fmaf.c. */ +#include diff --git a/sysdeps/tile/setjmp.S b/sysdeps/tile/setjmp.S new file mode 100644 index 0000000000..253990997e --- /dev/null +++ b/sysdeps/tile/setjmp.S @@ -0,0 +1,47 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + .text + + /* Keep traditional entry points in with sigsetjmp(). */ +ENTRY(setjmp) + { movei r1, 1; j 1f } +END(setjmp) + +ENTRY(_setjmp) + { movei r1, 0; j 1f } +END(_setjmp) +libc_hidden_def (_setjmp) + +ENTRY(__sigsetjmp) + FEEDBACK_ENTER(__sigsetjmp) +1: + move r2, r0 + +#define SAVE(r) { ST r2, r ; ADDI_PTR r2, r2, REGSIZE } + FOR_EACH_CALLEE_SAVED_REG(SAVE) + + mfspr r3, INTERRUPT_CRITICAL_SECTION + ST r2, r3 + j plt(__sigjmp_save) + jrp lr /* Keep the backtracer happy. */ +END(__sigsetjmp) diff --git a/sysdeps/tile/shlib-versions b/sysdeps/tile/shlib-versions new file mode 100644 index 0000000000..f50868ff64 --- /dev/null +++ b/sysdeps/tile/shlib-versions @@ -0,0 +1,2 @@ +# glibc 2.12 was released to customers; 2.15 was the first community version. +tile.*-.*-linux-gnu DEFAULT GLIBC_2.12 GLIBC_2.15 diff --git a/sysdeps/tile/stackinfo.h b/sysdeps/tile/stackinfo.h new file mode 100644 index 0000000000..e3233ac10f --- /dev/null +++ b/sysdeps/tile/stackinfo.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +#include + +/* On tile the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +/* Default to a non-executable stack. */ +#define DEFAULT_STACK_PERMS (PF_R|PF_W) + +/* Access to the stack pointer. The macros are used in alloca_account + for which they need to act as barriers as well, hence the additional + (unnecessary) parameters. */ +#define stackinfo_get_sp() \ + ({ void *p__; asm volatile ("move %0, sp" : "=r" (p__)); p__; }) +#if defined __tilegx__ && __WORDSIZE == 32 +#define __stackinfo_sub "subx" +#else +#define __stackinfo_sub "sub" +#endif +#define stackinfo_sub_sp(ptr) \ + ({ ptrdiff_t d__; \ + asm volatile (__stackinfo_sub " %0, %0, sp" : "=r" (d__) : "0" (ptr)); \ + d__; }) + +#endif /* stackinfo.h */ diff --git a/sysdeps/tile/sysdep.h b/sysdeps/tile/sysdep.h new file mode 100644 index 0000000000..758d28b9fa --- /dev/null +++ b/sysdeps/tile/sysdep.h @@ -0,0 +1,120 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifndef HAVE_ELF +# error "ELF is assumed." +#endif + +#ifndef NO_UNDERSCORES +# error "User-label prefix (underscore) assumed absent." +#endif + +#if defined __ASSEMBLER__ || defined REQUEST_ASSEMBLER_MACROS + +#include + +/* Make use of .type and .size directives. */ +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name; + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align 8; \ + C_LABEL(name) \ + cfi_startproc; \ + CALL_MCOUNT + +#undef END +#define END(name) \ + cfi_endproc; \ + ASM_SIZE_DIRECTIVE(name) + +/* Since C identifiers are not normally prefixed with an underscore + on this system, the asm identifier `syscall_error' intrudes on the + C name space. Make sure we use an innocuous name. */ +#define syscall_error __syscall_error +#define mcount __mcount + +/* If compiled for profiling, call `mcount' at the start of each function. + The mcount code requires the caller PC in r10. The `mcount' function + sets lr back to the value r10 had on entry when it returns. */ +#ifdef PROF +#define CALL_MCOUNT { move r10, lr; jal mcount } +#else +#define CALL_MCOUNT /* Do nothing. */ +#endif + +/* Local label name for asm code. */ +#define L(name) .L##name + +/* Specify the size in bytes of a machine register. */ +#ifdef __tilegx__ +#define REGSIZE 8 +#else +#define REGSIZE 4 +#endif + +/* Support a limited form of shared assembly between tile and tilegx. + The presumption is that LD/ST are used for manipulating registers. + Since opcode parsing is case-insensitive, we don't need to provide + definitions for these on tilegx. */ +#ifndef __tilegx__ +#define LD lw +#define LD4U lw +#define ST sw +#define ST4 sw +#define BNEZ bnz +#define BEQZ bz +#define BEQZT bzt +#define BGTZ bgz +#define CMPEQI seqi +#define CMPEQ seq +#define CMOVEQZ mvz +#define CMOVNEZ mvnz +#endif + +/* Provide "pointer-oriented" instruction variants. These differ not + just for tile vs tilegx, but also for tilegx -m64 vs -m32. */ +#if defined __tilegx__ && __WORDSIZE == 32 +#define ADD_PTR addx +#define ADDI_PTR addxi +#define ADDLI_PTR addxli +#define LD_PTR ld4s +#define ST_PTR st4 +#define SHL_PTR_ADD shl2add +#else +#define ADD_PTR add +#define ADDI_PTR addi +#define ADDLI_PTR addli +#define LD_PTR LD +#define ST_PTR ST +#ifdef __tilegx__ +#define SHL_PTR_ADD shl3add +#else +#define SHL_PTR_ADD s2a +#endif +#endif + +#endif /* __ASSEMBLER__ */ diff --git a/sysdeps/tile/tilegx/bits/atomic.h b/sysdeps/tile/tilegx/bits/atomic.h new file mode 100644 index 0000000000..1cb4e2b71b --- /dev/null +++ b/sysdeps/tile/tilegx/bits/atomic.h @@ -0,0 +1,50 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_ATOMIC_H +#define _BITS_ATOMIC_H 1 + +#include + +/* Pick appropriate 8- or 4-byte instruction. */ +#define __atomic_update(mem, v, op) \ + ((__typeof (*(mem))) (__typeof (*(mem) - *(mem))) \ + ((sizeof (*(mem)) == 8) ? \ + __insn_##op ((void *) (mem), (int64_t) (__typeof((v) - (v))) (v)) : \ + (sizeof (*(mem)) == 4) ? \ + __insn_##op##4 ((void *) (mem), (int32_t) (__typeof ((v) - (v))) (v)) : \ + __atomic_error_bad_argument_size())) + +#define atomic_compare_and_exchange_val_acq(mem, n, o) \ + ({ __insn_mtspr (SPR_CMPEXCH_VALUE, (int64_t) (__typeof ((o) - (o))) (o)); \ + __atomic_update (mem, n, cmpexch); }) +#define atomic_exchange_acq(mem, newvalue) \ + __atomic_update (mem, newvalue, exch) +#define atomic_exchange_and_add(mem, value) \ + __atomic_update (mem, value, fetchadd) +#define atomic_and_val(mem, mask) \ + __atomic_update (mem, mask, fetchand) +#define atomic_or_val(mem, mask) \ + __atomic_update (mem, mask, fetchor) +#define atomic_decrement_if_positive(mem) \ + __atomic_update (mem, -1, fetchaddgez) + +#include + +#endif /* bits/atomic.h */ diff --git a/sysdeps/tile/tilegx/bits/wordsize.h b/sysdeps/tile/tilegx/bits/wordsize.h new file mode 100644 index 0000000000..78f34817d5 --- /dev/null +++ b/sysdeps/tile/tilegx/bits/wordsize.h @@ -0,0 +1,8 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#ifdef __LP64__ +# define __WORDSIZE 64 +# define __WORDSIZE_COMPAT32 1 +#else +# define __WORDSIZE 32 +#endif diff --git a/sysdeps/tile/tilegx/memchr.c b/sysdeps/tile/tilegx/memchr.c new file mode 100644 index 0000000000..52a20b6daa --- /dev/null +++ b/sysdeps/tile/tilegx/memchr.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "string-endian.h" + +void * +__memchr (const void *s, int c, size_t n) +{ + const uint64_t *last_word_ptr; + const uint64_t *p; + const char *last_byte_ptr; + uintptr_t s_int; + uint64_t goal, before_mask, v, bits; + char *ret; + + if (__builtin_expect (n == 0, 0)) + { + /* Don't dereference any memory if the array is empty. */ + return NULL; + } + + /* Get an aligned pointer. */ + s_int = (uintptr_t) s; + p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + goal = 0x0101010101010101ULL * (uint8_t) c; + + /* Read the first word, but munge it so that bytes before the array + will not match goal. */ + before_mask = MASK (s_int); + v = (*p | before_mask) ^ (goal & before_mask); + + /* Compute the address of the last byte. */ + last_byte_ptr = (const char *) s + n - 1; + + /* Compute the address of the word containing the last byte. */ + last_word_ptr = (const uint64_t *) ((uintptr_t) last_byte_ptr & -8); + + while ((bits = __insn_v1cmpeq (v, goal)) == 0) + { + if (__builtin_expect (p == last_word_ptr, 0)) + { + /* We already read the last word in the array, so give up. */ + return NULL; + } + v = *++p; + } + + /* We found a match, but it might be in a byte past the end + of the array. */ + ret = ((char *) p) + (CFZ (bits) >> 3); + return (ret <= last_byte_ptr) ? ret : NULL; +} +weak_alias (__memchr, memchr) +libc_hidden_builtin_def (memchr) diff --git a/sysdeps/tile/tilegx/memcpy.c b/sysdeps/tile/tilegx/memcpy.c new file mode 100644 index 0000000000..35495be569 --- /dev/null +++ b/sysdeps/tile/tilegx/memcpy.c @@ -0,0 +1,196 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* Must be 8 bytes in size. */ +#define word_t uint64_t + +/* How many cache lines ahead should we prefetch? */ +#define PREFETCH_LINES_AHEAD 3 + +void * +__memcpy (void *__restrict dstv, const void *__restrict srcv, size_t n) +{ + char *__restrict dst1 = (char *) dstv; + const char *__restrict src1 = (const char *) srcv; + const char *__restrict src1_end; + const char *__restrict prefetch; + word_t *__restrict dst8; /* 8-byte pointer to destination memory. */ + word_t final; /* Final bytes to write to trailing word, if any */ + long i; + + if (n < 16) + { + for (; n; n--) + *dst1++ = *src1++; + return dstv; + } + + /* Locate the end of source memory we will copy. Don't prefetch + past this. */ + src1_end = src1 + n - 1; + + /* Prefetch ahead a few cache lines, but not past the end. */ + prefetch = src1; + for (i = 0; i < PREFETCH_LINES_AHEAD; i++) + { + __insn_prefetch (prefetch); + prefetch += CHIP_L2_LINE_SIZE (); + prefetch = (prefetch > src1_end) ? prefetch : src1; + } + + /* Copy bytes until dst is word-aligned. */ + for (; (uintptr_t) dst1 & (sizeof (word_t) - 1); n--) + *dst1++ = *src1++; + + /* 8-byte pointer to destination memory. */ + dst8 = (word_t *) dst1; + + if (__builtin_expect ((uintptr_t) src1 & (sizeof (word_t) - 1), 0)) + { + /* Misaligned copy. Copy 8 bytes at a time, but don't bother + with other fanciness. + TODO: Consider prefetching and using wh64 as well. */ + + /* Create an aligned src8. */ + const word_t *__restrict src8 = + (const word_t *) ((uintptr_t) src1 & -sizeof (word_t)); + word_t b; + + word_t a = *src8++; + for (; n >= sizeof (word_t); n -= sizeof (word_t)) + { + b = *src8++; + a = __insn_dblalign (a, b, src1); + *dst8++ = a; + a = b; + } + + if (n == 0) + return dstv; + + b = ((const char *) src8 <= src1_end) ? *src8 : 0; + + /* Final source bytes to write to trailing partial word, if any. */ + final = __insn_dblalign (a, b, src1); + } + else + { + /* Aligned copy. */ + + const word_t *__restrict src8 = (const word_t *) src1; + + /* src8 and dst8 are both word-aligned. */ + if (n >= CHIP_L2_LINE_SIZE ()) + { + /* Copy until 'dst' is cache-line-aligned. */ + for (; (uintptr_t) dst8 & (CHIP_L2_LINE_SIZE () - 1); + n -= sizeof (word_t)) + *dst8++ = *src8++; + + for (; n >= CHIP_L2_LINE_SIZE ();) + { + __insn_wh64 (dst8); + + /* Prefetch and advance to next line to prefetch, but + don't go past the end. */ + __insn_prefetch (prefetch); + prefetch += CHIP_L2_LINE_SIZE (); + prefetch = (prefetch > src1_end) ? prefetch : + (const char *) src8; + + /* Copy an entire cache line. Manually unrolled to + avoid idiosyncracies of compiler unrolling. */ +#define COPY_WORD(offset) ({ dst8[offset] = src8[offset]; n -= 8; }) + COPY_WORD (0); + COPY_WORD (1); + COPY_WORD (2); + COPY_WORD (3); + COPY_WORD (4); + COPY_WORD (5); + COPY_WORD (6); + COPY_WORD (7); +#if CHIP_L2_LINE_SIZE() != 64 +# error "Fix code that assumes particular L2 cache line size." +#endif + + dst8 += CHIP_L2_LINE_SIZE () / sizeof (word_t); + src8 += CHIP_L2_LINE_SIZE () / sizeof (word_t); + } + } + + for (; n >= sizeof (word_t); n -= sizeof (word_t)) + *dst8++ = *src8++; + + if (__builtin_expect (n == 0, 1)) + return dstv; + + final = *src8; + } + + /* n != 0 if we get here. Write out any trailing bytes. */ + dst1 = (char *) dst8; +#ifndef __BIG_ENDIAN__ + if (n & 4) + { + *(uint32_t *) dst1 = final; + dst1 += 4; + final >>= 32; + n &= 3; + } + if (n & 2) + { + *(uint16_t *) dst1 = final; + dst1 += 2; + final >>= 16; + n &= 1; + } + if (n) + *(uint8_t *) dst1 = final; +#else + if (n & 4) + { + *(uint32_t *) dst1 = final >> 32; + dst1 += 4; + } + else + { + final >>= 32; + } + if (n & 2) + { + *(uint16_t *) dst1 = final >> 16; + dst1 += 2; + } + else + { + final >>= 16; + } + if (n & 1) + *(uint8_t *) dst1 = final >> 8; +#endif + + return dstv; +} +weak_alias (__memcpy, memcpy) +libc_hidden_builtin_def (memcpy) diff --git a/sysdeps/tile/tilegx/memset.c b/sysdeps/tile/tilegx/memset.c new file mode 100644 index 0000000000..ddde05fea3 --- /dev/null +++ b/sysdeps/tile/tilegx/memset.c @@ -0,0 +1,151 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +void * +__memset (void *s, int c, size_t n) +{ + uint64_t *out64; + int n64, to_align64; + uint64_t v64; + uint8_t *out8 = s; + + /* Experimentation shows that a trivial tight loop is a win up until + around a size of 20, where writing a word at a time starts to win. */ +#define BYTE_CUTOFF 20 + +#if BYTE_CUTOFF < 7 + /* This must be at least at least this big, or some code later + on doesn't work. */ +# error "BYTE_CUTOFF is too small." +#endif + + if (n < BYTE_CUTOFF) + { + /* Strangely, this turns out to be the tightest way to write + this loop. */ + if (n != 0) + { + do + { + /* Strangely, combining these into one line performs worse. */ + *out8 = c; + out8++; + } + while (--n != 0); + } + + return s; + } + + /* Align 'out8'. We know n >= 7 so this won't write past the end. */ + while (((uintptr_t) out8 & 7) != 0) + { + *out8++ = c; + --n; + } + + /* Align 'n'. */ + while (n & 7) + out8[--n] = c; + + out64 = (uint64_t *) out8; + n64 = n >> 3; + + /* Tile input byte out to 64 bits. */ + v64 = 0x0101010101010101ULL * (uint8_t) c; + + /* This must be at least 8 or the following loop doesn't work. */ +#define CACHE_LINE_SIZE_IN_DOUBLEWORDS (CHIP_L2_LINE_SIZE() / 8) + + /* Determine how many words we need to emit before the 'out32' + pointer becomes aligned modulo the cache line size. */ + to_align64 = (-((uintptr_t) out64 >> 3)) & + (CACHE_LINE_SIZE_IN_DOUBLEWORDS - 1); + + /* Only bother aligning and using wh64 if there is at least + one full cache line to process. This check also prevents + overrunning the end of the buffer with alignment words. */ + if (to_align64 <= n64 - CACHE_LINE_SIZE_IN_DOUBLEWORDS) + { + int lines_left; + + /* Align out64 mod the cache line size so we can use wh64. */ + n64 -= to_align64; + for (; to_align64 != 0; to_align64--) + { + *out64 = v64; + out64++; + } + + /* Use unsigned divide to turn this into a right shift. */ + lines_left = (unsigned) n64 / CACHE_LINE_SIZE_IN_DOUBLEWORDS; + + do + { + /* Only wh64 a few lines at a time, so we don't exceed the + maximum number of victim lines. */ + int x = ((lines_left < CHIP_MAX_OUTSTANDING_VICTIMS ()) ? lines_left + : CHIP_MAX_OUTSTANDING_VICTIMS ()); + uint64_t *wh = out64; + int i = x; + int j; + + lines_left -= x; + + do + { + __insn_wh64 (wh); + wh += CACHE_LINE_SIZE_IN_DOUBLEWORDS; + } + while (--i); + + for (j = x * (CACHE_LINE_SIZE_IN_DOUBLEWORDS / 4); j != 0; j--) + { + *out64++ = v64; + *out64++ = v64; + *out64++ = v64; + *out64++ = v64; + } + } + while (lines_left != 0); + + /* We processed all full lines above, so only this many + words remain to be processed. */ + n64 &= CACHE_LINE_SIZE_IN_DOUBLEWORDS - 1; + } + + /* Now handle any leftover values. */ + if (n64 != 0) + { + do + { + *out64 = v64; + out64++; + } + while (--n64 != 0); + } + + return s; +} +weak_alias (__memset, memset) +libc_hidden_builtin_def (memset) diff --git a/sysdeps/tile/tilegx/memusage.h b/sysdeps/tile/tilegx/memusage.h new file mode 100644 index 0000000000..7afb50a929 --- /dev/null +++ b/sysdeps/tile/tilegx/memusage.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define GETSP() ({ register uintptr_t stack_ptr asm ("sp"); stack_ptr; }) + +#define GETTIME(low,high) \ + { \ + uint64_t cycles = __insn_mfspr (SPR_CYCLE); \ + low = cycles & 0xffffffff; \ + high = cycles >> 32; \ + } + +#include diff --git a/sysdeps/tile/tilegx/rawmemchr.c b/sysdeps/tile/tilegx/rawmemchr.c new file mode 100644 index 0000000000..cd0f2fd878 --- /dev/null +++ b/sysdeps/tile/tilegx/rawmemchr.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "string-endian.h" + +void * +__rawmemchr (const void *s, int c) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + const uint64_t goal = 0x0101010101010101ULL * (uint8_t) c; + + /* Read the first word, but munge it so that bytes before the array + will not match goal. */ + const uint64_t before_mask = MASK (s_int); + uint64_t v = (*p | before_mask) ^ (goal & before_mask); + + uint64_t bits; + while ((bits = __insn_v1cmpeq (v, goal)) == 0) + v = *++p; + + return ((char *) p) + (CFZ (bits) >> 3); +} +libc_hidden_def (__rawmemchr) +weak_alias (__rawmemchr, rawmemchr) diff --git a/sysdeps/tile/tilegx/strchr.c b/sysdeps/tile/tilegx/strchr.c new file mode 100644 index 0000000000..2dc75060d6 --- /dev/null +++ b/sysdeps/tile/tilegx/strchr.c @@ -0,0 +1,68 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "string-endian.h" + +#undef strchr + +char * +strchr (const char *s, int c) +{ + int z, g; + + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + const uint64_t goal = 0x0101010101010101ULL * (uint8_t) c; + + /* Read the first aligned word, but force bytes before the string to + match neither zero nor goal (we make sure the high bit of each byte + is 1, and the low 7 bits are all the opposite of the goal byte). */ + const uint64_t before_mask = MASK (s_int); + uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui (before_mask, 1)); + + uint64_t zero_matches, goal_matches; + while (1) + { + /* Look for a terminating '\0'. */ + zero_matches = __insn_v1cmpeqi (v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_v1cmpeq (v, goal); + + if (__builtin_expect ((zero_matches | goal_matches) != 0, 0)) + break; + + v = *++p; + } + + z = CFZ (zero_matches); + g = CFZ (goal_matches); + + /* If we found c before '\0' we got a match. Note that if c == '\0' + then g == z, and we correctly return the address of the '\0' + rather than NULL. */ + return (g <= z) ? ((char *) p) + (g >> 3) : NULL; +} +weak_alias (strchr, index) +libc_hidden_builtin_def (strchr) diff --git a/sysdeps/tile/tilegx/strchrnul.c b/sysdeps/tile/tilegx/strchrnul.c new file mode 100644 index 0000000000..bb165b5b51 --- /dev/null +++ b/sysdeps/tile/tilegx/strchrnul.c @@ -0,0 +1,65 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "string-endian.h" + +char * +__strchrnul (const char *s, int c) +{ + int z, g; + + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + const uint64_t goal = 0x0101010101010101ULL * (uint8_t) c; + + /* Read the first aligned word, but force bytes before the string to + match neither zero nor goal (we make sure the high bit of each byte + is 1, and the low 7 bits are all the opposite of the goal byte). */ + const uint64_t before_mask = MASK (s_int); + uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui (before_mask, 1)); + + uint64_t zero_matches, goal_matches; + while (1) + { + /* Look for a terminating '\0'. */ + zero_matches = __insn_v1cmpeqi (v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_v1cmpeq (v, goal); + + if (__builtin_expect ((zero_matches | goal_matches) != 0, 0)) + break; + + v = *++p; + } + + z = CFZ (zero_matches); + g = CFZ (goal_matches); + + /* Return a pointer to the NUL or goal, whichever is first. */ + if (z < g) + g = z; + return ((char *) p) + (g >> 3); +} +weak_alias (__strchrnul, strchrnul) diff --git a/sysdeps/tile/tilegx/string-endian.h b/sysdeps/tile/tilegx/string-endian.h new file mode 100644 index 0000000000..29ca793af1 --- /dev/null +++ b/sysdeps/tile/tilegx/string-endian.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +/* Provide a mask based on the pointer alignment that + sets up non-zero bytes before the beginning of the string. + The MASK expression works because shift counts are taken mod 64. + Also, specify how to count "first" and "last" bits + when the bits have been read as a word. */ + +#ifndef __BIG_ENDIAN__ +#define MASK(x) (__insn_shl(1ULL, (x << 3)) - 1) +#define NULMASK(x) ((2ULL << x) - 1) +#define CFZ(x) __insn_ctz(x) +#define REVCZ(x) __insn_clz(x) +#else +#define MASK(x) (__insn_shl(-2LL, ((-x << 3) - 1))) +#define NULMASK(x) (-2LL << (63 - x)) +#define CFZ(x) __insn_clz(x) +#define REVCZ(x) __insn_ctz(x) +#endif diff --git a/sysdeps/tile/tilegx/strlen.c b/sysdeps/tile/tilegx/strlen.c new file mode 100644 index 0000000000..a729e991de --- /dev/null +++ b/sysdeps/tile/tilegx/strlen.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "string-endian.h" + +size_t +strlen (const char *s) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Read and MASK the first word. */ + uint64_t v = *p | MASK (s_int); + + uint64_t bits; + while ((bits = __insn_v1cmpeqi (v, 0)) == 0) + v = *++p; + + return ((const char *) p) + (CFZ (bits) >> 3) - s; +} +libc_hidden_builtin_def (strlen) diff --git a/sysdeps/tile/tilegx/strrchr.c b/sysdeps/tile/tilegx/strrchr.c new file mode 100644 index 0000000000..9724d02c1b --- /dev/null +++ b/sysdeps/tile/tilegx/strrchr.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "string-endian.h" + +char * +strrchr (const char *s, int c) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + const uint64_t goal = 0x0101010101010101ULL * (uint8_t) c; + + /* Read the first aligned word, but force bytes before the string to + match neither zero nor goal (we make sure the high bit of each byte + is 1, and the low 7 bits are all the opposite of the goal byte). */ + const uint64_t before_mask = MASK (s_int); + uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui (before_mask, 1)); + const char *found = NULL; + uint64_t zero_matches, goal_matches; + while (1) + { + /* Look for a terminating '\0'. */ + zero_matches = __insn_v1cmpeqi (v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_v1cmpeq (v, goal); + + /* If we found the goal, record the last offset. */ + if (__builtin_expect (goal_matches != 0, 0)) + { + if (__builtin_expect (zero_matches != 0, 0)) + { + /* Clear any goal after the first zero. */ + int first_nul = CFZ (zero_matches); + goal_matches &= NULMASK (first_nul); + } + if (__builtin_expect (goal_matches != 0, 1)) + found = ((char *) p) + 7 - (REVCZ (goal_matches) >> 3); + } + + if (__builtin_expect (zero_matches != 0, 0)) + return (char *) found; + + v = *++p; + } +} +weak_alias (strrchr, rindex) +libc_hidden_builtin_def (strrchr) diff --git a/sysdeps/tile/tilegx/tilegx32/Implies b/sysdeps/tile/tilegx/tilegx32/Implies new file mode 100644 index 0000000000..993b7f4cd1 --- /dev/null +++ b/sysdeps/tile/tilegx/tilegx32/Implies @@ -0,0 +1,3 @@ +tile/tilegx +tile +wordsize-32 diff --git a/sysdeps/tile/tilegx/tilegx64/Implies b/sysdeps/tile/tilegx/tilegx64/Implies new file mode 100644 index 0000000000..eb0686e0e6 --- /dev/null +++ b/sysdeps/tile/tilegx/tilegx64/Implies @@ -0,0 +1,3 @@ +tile/tilegx +tile +wordsize-64 diff --git a/sysdeps/tile/tilepro/Implies b/sysdeps/tile/tilepro/Implies new file mode 100644 index 0000000000..709e1dc122 --- /dev/null +++ b/sysdeps/tile/tilepro/Implies @@ -0,0 +1,2 @@ +tile +wordsize-32 diff --git a/sysdeps/tile/tilepro/bits/atomic.h b/sysdeps/tile/tilepro/bits/atomic.h new file mode 100644 index 0000000000..9d996cbcfd --- /dev/null +++ b/sysdeps/tile/tilepro/bits/atomic.h @@ -0,0 +1,82 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_ATOMIC_H +#define _BITS_ATOMIC_H 1 + +#include + +/* 32-bit integer compare-and-exchange. */ +static __inline __attribute__ ((always_inline)) +int __atomic_cmpxchg_32 (volatile int *mem, int newval, int oldval) +{ + int result; + __asm__ __volatile__ ("swint1" + : "=R00" (result), "=m" (*mem) + : "R10" (__NR_FAST_cmpxchg), "R00" (mem), + "R01" (oldval), "R02" (newval), "m" (*mem) + : "r20", "r21", "r22", "r23", "r24", + "r25", "r26", "r27", "r28", "r29", "memory"); + return result; +} + +#define atomic_compare_and_exchange_val_acq(mem, n, o) \ + ((__typeof (*(mem))) \ + ((sizeof (*(mem)) == 4) ? \ + __atomic_cmpxchg_32 ((int *) (mem), (int) (n), (int) (o)) : \ + __atomic_error_bad_argument_size())) + +/* Atomically compute: + int old = *ptr; + *ptr = (old & mask) + addend; + return old; */ + +static __inline __attribute__ ((always_inline)) +int __atomic_update_32 (volatile int *mem, int mask, int addend) +{ + int result; + __asm__ __volatile__ ("swint1" + : "=R00" (result), "=m" (*mem) + : "R10" (__NR_FAST_atomic_update), "R00" (mem), + "R01" (mask), "R02" (addend), "m" (*mem) + : "r20", "r21", "r22", "r23", "r24", + "r25", "r26", "r27", "r28", "r29", "memory"); + return result; +} + +/* Size-checked verson of __atomic_update_32. */ +#define __atomic_update(mem, mask, addend) \ + ((__typeof (*(mem))) \ + ((sizeof (*(mem)) == 4) ? \ + __atomic_update_32 ((int *) (mem), (int) (mask), (int) (addend)) : \ + __atomic_error_bad_argument_size ())) + +#define atomic_exchange_acq(mem, newvalue) \ + __atomic_update ((mem), 0, (newvalue)) +#define atomic_exchange_and_add(mem, value) \ + __atomic_update ((mem), -1, (value)) +#define atomic_and_val(mem, mask) \ + __atomic_update ((mem), (mask), 0) +#define atomic_or_val(mem, mask) \ + ({ __typeof (mask) __att1_v = (mask); \ + __atomic_update ((mem), ~__att1_v, __att1_v); }) + +#include + +#endif /* bits/atomic.h */ diff --git a/sysdeps/tile/tilepro/bits/wordsize.h b/sysdeps/tile/tilepro/bits/wordsize.h new file mode 100644 index 0000000000..da587a2f12 --- /dev/null +++ b/sysdeps/tile/tilepro/bits/wordsize.h @@ -0,0 +1,3 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#define __WORDSIZE 32 diff --git a/sysdeps/tile/tilepro/memchr.c b/sysdeps/tile/tilepro/memchr.c new file mode 100644 index 0000000000..125fd0d39b --- /dev/null +++ b/sysdeps/tile/tilepro/memchr.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +void * +__memchr (const void *s, int c, size_t n) +{ + const uint32_t *last_word_ptr; + const uint32_t *p; + const char *last_byte_ptr; + uintptr_t s_int; + uint32_t goal, before_mask, v, bits; + char *ret; + + if (__builtin_expect (n == 0, 0)) + { + /* Don't dereference any memory if the array is empty. */ + return NULL; + } + + /* Get an aligned pointer. */ + s_int = (uintptr_t) s; + p = (const uint32_t *) (s_int & -4); + + /* Create four copies of the byte for which we are looking. */ + goal = 0x01010101 * (uint8_t) c; + + /* Read the first word, but munge it so that bytes before the array + will not match goal. Note that this shift count expression works + because we know shift counts are taken mod 32. */ + before_mask = (1 << (s_int << 3)) - 1; + v = (*p | before_mask) ^ (goal & before_mask); + + /* Compute the address of the last byte. */ + last_byte_ptr = (const char *) s + n - 1; + + /* Compute the address of the word containing the last byte. */ + last_word_ptr = (const uint32_t *) ((uintptr_t) last_byte_ptr & -4); + + while ((bits = __insn_seqb (v, goal)) == 0) + { + if (__builtin_expect (p == last_word_ptr, 0)) + { + /* We already read the last word in the array, so give up. */ + return NULL; + } + v = *++p; + } + + /* We found a match, but it might be in a byte past the end of the array. */ + ret = ((char *) p) + (__insn_ctz (bits) >> 3); + return (ret <= last_byte_ptr) ? ret : NULL; +} +weak_alias (__memchr, memchr) +libc_hidden_builtin_def (memchr) diff --git a/sysdeps/tile/tilepro/memcpy.S b/sysdeps/tile/tilepro/memcpy.S new file mode 100644 index 0000000000..4bddeede4b --- /dev/null +++ b/sysdeps/tile/tilepro/memcpy.S @@ -0,0 +1,398 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + .text +ENTRY (__memcpy) + FEEDBACK_ENTER(__memcpy) + + /* r0 is the dest, r1 is the source, r2 is the size. */ + + /* Save aside original dest so we can return it at the end. */ + { sw sp, lr; move r23, r0; or r4, r0, r1 } + cfi_offset (lr, 0) + + /* Check for an empty size. */ + { bz r2, .Ldone; andi r4, r4, 3 } + + /* Check for an unaligned source or dest. */ + { bnz r4, .Lcopy_unaligned_maybe_many; addli r4, r2, -256 } + +.Lcheck_aligned_copy_size: + /* If we are copying < 256 bytes, branch to simple case. */ + { blzt r4, .Lcopy_8_check; slti_u r8, r2, 8 } + + /* Copying >= 256 bytes, so jump to complex prefetching loop. */ + { andi r6, r1, 63; j .Lcopy_many } + +/* Aligned 4 byte at a time copy loop. */ + +.Lcopy_8_loop: + /* Copy two words at a time to hide load latency. */ + { lw r3, r1; addi r1, r1, 4; slti_u r8, r2, 16 } + { lw r4, r1; addi r1, r1, 4 } + { sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 } + { sw r0, r4; addi r0, r0, 4; addi r2, r2, -4 } +.Lcopy_8_check: + { bzt r8, .Lcopy_8_loop; slti_u r4, r2, 4 } + + /* Copy odd leftover word, if any. */ + { bnzt r4, .Lcheck_odd_stragglers } + { lw r3, r1; addi r1, r1, 4 } + { sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 } + +.Lcheck_odd_stragglers: + { bnz r2, .Lcopy_unaligned_few } + +.Ldone: + { move r0, r23; jrp lr } + +/* Prefetching multiple cache line copy handler (for large transfers). */ + + /* Copy words until r1 is cache-line-aligned. */ +.Lalign_loop: + { lw r3, r1; addi r1, r1, 4 } + { andi r6, r1, 63 } + { sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 } +.Lcopy_many: + { bnzt r6, .Lalign_loop; addi r9, r0, 63 } + + { addi r3, r1, 60; andi r9, r9, -64 } + + /* No need to prefetch dst, we'll just do the wh64 + right before we copy a line. */ + { lw r5, r3; addi r3, r3, 64; movei r4, 1 } + /* Intentionally stall for a few cycles to leave L2 cache alone. */ + { bnzt zero, .; move r27, lr } + { lw r6, r3; addi r3, r3, 64 } + /* Intentionally stall for a few cycles to leave L2 cache alone. */ + { bnzt zero, . } + { lw r7, r3; addi r3, r3, 64 } + /* Intentionally stall for a few cycles to leave L2 cache alone. */ + { bz zero, .Lbig_loop2 } + + /* On entry to this loop: + - r0 points to the start of dst line 0 + - r1 points to start of src line 0 + - r2 >= (256 - 60), only the first time the loop trips. + - r3 contains r1 + 128 + 60 [pointer to end of source line 2] + This is our prefetch address. When we get near the end + rather than prefetching off the end this is changed to point + to some "safe" recently loaded address. + - r5 contains *(r1 + 60) [i.e. last word of source line 0] + - r6 contains *(r1 + 64 + 60) [i.e. last word of source line 1] + - r9 contains ((r0 + 63) & -64) + [start of next dst cache line.] */ + +.Lbig_loop: + { jal .Lcopy_line2; add r15, r1, r2 } + +.Lbig_loop2: + /* Copy line 0, first stalling until r5 is ready. */ + { move r12, r5; lw r16, r1 } + { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 } + /* Prefetch several lines ahead. */ + { lw r5, r3; addi r3, r3, 64 } + { jal .Lcopy_line } + + /* Copy line 1, first stalling until r6 is ready. */ + { move r12, r6; lw r16, r1 } + { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 } + /* Prefetch several lines ahead. */ + { lw r6, r3; addi r3, r3, 64 } + { jal .Lcopy_line } + + /* Copy line 2, first stalling until r7 is ready. */ + { move r12, r7; lw r16, r1 } + { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 } + /* Prefetch several lines ahead. */ + { lw r7, r3; addi r3, r3, 64 } + /* Use up a caches-busy cycle by jumping back to the top of the + loop. Might as well get it out of the way now. */ + { j .Lbig_loop } + + + /* On entry: + - r0 points to the destination line. + - r1 points to the source line. + - r3 is the next prefetch address. + - r9 holds the last address used for wh64. + - r12 = WORD_15 + - r16 = WORD_0. + - r17 == r1 + 16. + - r27 holds saved lr to restore. + + On exit: + - r0 is incremented by 64. + - r1 is incremented by 64, unless that would point to a word + beyond the end of the source array, in which case it is redirected + to point to an arbitrary word already in the cache. + - r2 is decremented by 64. + - r3 is unchanged, unless it points to a word beyond the + end of the source array, in which case it is redirected + to point to an arbitrary word already in the cache. + Redirecting is OK since if we are that close to the end + of the array we will not come back to this subroutine + and use the contents of the prefetched address. + - r4 is nonzero iff r2 >= 64. + - r9 is incremented by 64, unless it points beyond the + end of the last full destination cache line, in which + case it is redirected to a "safe address" that can be + clobbered (sp - 64) + - lr contains the value in r27. */ + +/* r26 unused */ + +.Lcopy_line: + /* TODO: when r3 goes past the end, we would like to redirect it + to prefetch the last partial cache line (if any) just once, for the + benefit of the final cleanup loop. But we don't want to + prefetch that line more than once, or subsequent prefetches + will go into the RTF. But then .Lbig_loop should unconditionally + branch to top of loop to execute final prefetch, and its + nop should become a conditional branch. */ + + /* We need two non-memory cycles here to cover the resources + used by the loads initiated by the caller. */ + { add r15, r1, r2 } +.Lcopy_line2: + { slt_u r13, r3, r15; addi r17, r1, 16 } + + /* NOTE: this will stall for one cycle as L1 is busy. */ + + /* Fill second L1D line. */ + { lw r17, r17; addi r1, r1, 48; mvz r3, r13, r1 } /* r17 = WORD_4 */ + + /* Prepare destination line for writing. */ + { wh64 r9; addi r9, r9, 64 } + + /* Load seven words that are L1D hits to cover wh64 L2 usage. */ + + /* Load the three remaining words from the last L1D line, which + we know has already filled the L1D. */ + { lw r4, r1; addi r1, r1, 4; addi r20, r1, 16 } /* r4 = WORD_12 */ + { lw r8, r1; addi r1, r1, 4; slt_u r13, r20, r15 }/* r8 = WORD_13 */ + { lw r11, r1; addi r1, r1, -52; mvz r20, r13, r1 } /* r11 = WORD_14 */ + + /* Load the three remaining words from the first L1D line, first + stalling until it has filled by "looking at" r16. */ + { lw r13, r1; addi r1, r1, 4; move zero, r16 } /* r13 = WORD_1 */ + { lw r14, r1; addi r1, r1, 4 } /* r14 = WORD_2 */ + { lw r15, r1; addi r1, r1, 8; addi r10, r0, 60 } /* r15 = WORD_3 */ + + /* Load second word from the second L1D line, first + stalling until it has filled by "looking at" r17. */ + { lw r19, r1; addi r1, r1, 4; move zero, r17 } /* r19 = WORD_5 */ + + /* Store last word to the destination line, potentially dirtying it + for the first time, which keeps the L2 busy for two cycles. */ + { sw r10, r12 } /* store(WORD_15) */ + + /* Use two L1D hits to cover the sw L2 access above. */ + { lw r10, r1; addi r1, r1, 4 } /* r10 = WORD_6 */ + { lw r12, r1; addi r1, r1, 4 } /* r12 = WORD_7 */ + + /* Fill third L1D line. */ + { lw r18, r1; addi r1, r1, 4 } /* r18 = WORD_8 */ + + /* Store first L1D line. */ + { sw r0, r16; addi r0, r0, 4; add r16, r0, r2 } /* store(WORD_0) */ + { sw r0, r13; addi r0, r0, 4; andi r16, r16, -64 } /* store(WORD_1) */ + { sw r0, r14; addi r0, r0, 4; slt_u r16, r9, r16 } /* store(WORD_2) */ + { sw r0, r15; addi r0, r0, 4; addi r13, sp, -64 } /* store(WORD_3) */ + + /* Store second L1D line. */ + { sw r0, r17; addi r0, r0, 4; mvz r9, r16, r13 }/* store(WORD_4) */ + { sw r0, r19; addi r0, r0, 4 } /* store(WORD_5) */ + { sw r0, r10; addi r0, r0, 4 } /* store(WORD_6) */ + { sw r0, r12; addi r0, r0, 4 } /* store(WORD_7) */ + + { lw r13, r1; addi r1, r1, 4; move zero, r18 } /* r13 = WORD_9 */ + { lw r14, r1; addi r1, r1, 4 } /* r14 = WORD_10 */ + { lw r15, r1; move r1, r20 } /* r15 = WORD_11 */ + + /* Store third L1D line. */ + { sw r0, r18; addi r0, r0, 4 } /* store(WORD_8) */ + { sw r0, r13; addi r0, r0, 4 } /* store(WORD_9) */ + { sw r0, r14; addi r0, r0, 4 } /* store(WORD_10) */ + { sw r0, r15; addi r0, r0, 4 } /* store(WORD_11) */ + + /* Store rest of fourth L1D line. */ + { sw r0, r4; addi r0, r0, 4 } /* store(WORD_12) */ + { + sw r0, r8 /* store(WORD_13) */ + addi r0, r0, 4 + /* Will r2 be > 64 after we subtract 64 below? */ + shri r4, r2, 7 + } + { + sw r0, r11 /* store(WORD_14) */ + addi r0, r0, 8 + /* Record 64 bytes successfully copied. */ + addi r2, r2, -64 + } + + { jrp lr; move lr, r27 } + + /* Convey to the backtrace library that the stack frame is + size zero, and the real return address is on the stack + rather than in 'lr'. */ + { info 8 } + + .align 64 +.Lcopy_unaligned_maybe_many: + /* Skip the setup overhead if we aren't copying many bytes. */ + { slti_u r8, r2, 20; sub r4, zero, r0 } + { bnzt r8, .Lcopy_unaligned_few; andi r4, r4, 3 } + { bz r4, .Ldest_is_word_aligned; add r18, r1, r2 } + +/* Unaligned 4 byte at a time copy handler. */ + + /* Copy single bytes until r0 == 0 mod 4, so we can store words. */ +.Lalign_dest_loop: + { lb_u r3, r1; addi r1, r1, 1; addi r4, r4, -1 } + { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 } + { bnzt r4, .Lalign_dest_loop; andi r3, r1, 3 } + + /* If source and dest are now *both* aligned, do an aligned copy. */ + { bz r3, .Lcheck_aligned_copy_size; addli r4, r2, -256 } + +.Ldest_is_word_aligned: + + { andi r8, r0, 63; lwadd_na r6, r1, 4} + { slti_u r9, r2, 64; bz r8, .Ldest_is_L2_line_aligned } + + /* This copies unaligned words until either there are fewer + than 4 bytes left to copy, or until the destination pointer + is cache-aligned, whichever comes first. + + On entry: + - r0 is the next store address. + - r1 points 4 bytes past the load address corresponding to r0. + - r2 >= 4 + - r6 is the next aligned word loaded. */ +.Lcopy_unaligned_src_words: + { lwadd_na r7, r1, 4; slti_u r8, r2, 4 + 4 } + /* stall */ + { dword_align r6, r7, r1; slti_u r9, r2, 64 + 4 } + { swadd r0, r6, 4; addi r2, r2, -4 } + { bnz r8, .Lcleanup_unaligned_words; andi r8, r0, 63 } + { bnzt r8, .Lcopy_unaligned_src_words; move r6, r7 } + + /* On entry: + - r0 is the next store address. + - r1 points 4 bytes past the load address corresponding to r0. + - r2 >= 4 (# of bytes left to store). + - r6 is the next aligned src word value. + - r9 = (r2 < 64U). + - r18 points one byte past the end of source memory. */ +.Ldest_is_L2_line_aligned: + + { + /* Not a full cache line remains. */ + bnz r9, .Lcleanup_unaligned_words + move r7, r6 + } + + /* r2 >= 64 */ + + /* Kick off two prefetches, but don't go past the end. */ + { addi r3, r1, 63 - 4; addi r8, r1, 64 + 63 - 4 } + { prefetch r3; move r3, r8; slt_u r8, r8, r18 } + { mvz r3, r8, r1; addi r8, r3, 64 } + { prefetch r3; move r3, r8; slt_u r8, r8, r18 } + { mvz r3, r8, r1; movei r17, 0 } + +.Lcopy_unaligned_line: + /* Prefetch another line. */ + { prefetch r3; addi r15, r1, 60; addi r3, r3, 64 } + /* Fire off a load of the last word we are about to copy. */ + { lw_na r15, r15; slt_u r8, r3, r18 } + + { mvz r3, r8, r1; wh64 r0 } + + /* This loop runs twice. + + On entry: + - r17 is even before the first iteration, and odd before + the second. It is incremented inside the loop. Encountering + an even value at the end of the loop makes it stop. */ +.Lcopy_half_an_unaligned_line: + { + /* Stall until the last byte is ready. In the steady state this + guarantees all words to load below will be in the L2 cache, which + avoids shunting the loads to the RTF. */ + move zero, r15 + lwadd_na r7, r1, 16 + } + { lwadd_na r11, r1, 12 } + { lwadd_na r14, r1, -24 } + { lwadd_na r8, r1, 4 } + { lwadd_na r9, r1, 4 } + { + lwadd_na r10, r1, 8 + /* r16 = (r2 < 64), after we subtract 32 from r2 below. */ + slti_u r16, r2, 64 + 32 + } + { lwadd_na r12, r1, 4; addi r17, r17, 1 } + { lwadd_na r13, r1, 8; dword_align r6, r7, r1 } + { swadd r0, r6, 4; dword_align r7, r8, r1 } + { swadd r0, r7, 4; dword_align r8, r9, r1 } + { swadd r0, r8, 4; dword_align r9, r10, r1 } + { swadd r0, r9, 4; dword_align r10, r11, r1 } + { swadd r0, r10, 4; dword_align r11, r12, r1 } + { swadd r0, r11, 4; dword_align r12, r13, r1 } + { swadd r0, r12, 4; dword_align r13, r14, r1 } + { swadd r0, r13, 4; addi r2, r2, -32 } + { move r6, r14; bbst r17, .Lcopy_half_an_unaligned_line } + + { bzt r16, .Lcopy_unaligned_line; move r7, r6 } + + /* On entry: + - r0 is the next store address. + - r1 points 4 bytes past the load address corresponding to r0. + - r2 >= 0 (# of bytes left to store). + - r7 is the next aligned src word value. */ +.Lcleanup_unaligned_words: + /* Handle any trailing bytes. */ + { bz r2, .Lcopy_unaligned_done; slti_u r8, r2, 4 } + { bzt r8, .Lcopy_unaligned_src_words; move r6, r7 } + + /* Move r1 back to the point where it corresponds to r0. */ + { addi r1, r1, -4 } + + /* Fall through */ + +/* 1 byte at a time copy handler. */ + +.Lcopy_unaligned_few: + { lb_u r3, r1; addi r1, r1, 1 } + { sb r0, r3; addi r0, r0, 1; addi r2, r2, -1 } + { bnzt r2, .Lcopy_unaligned_few } + +.Lcopy_unaligned_done: + + { move r0, r23; jrp lr } + +END (__memcpy) + +weak_alias (__memcpy, memcpy) +libc_hidden_builtin_def (memcpy) diff --git a/sysdeps/tile/tilepro/memset.c b/sysdeps/tile/tilepro/memset.c new file mode 100644 index 0000000000..bfdc3d4193 --- /dev/null +++ b/sysdeps/tile/tilepro/memset.c @@ -0,0 +1,152 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +void * +__memset (void *s, int c, size_t n) +{ + uint32_t *out32; + int n32; + uint32_t v16, v32; + uint8_t *out8 = s; + int to_align32; + + /* Experimentation shows that a trivial tight loop is a win up until + around a size of 20, where writing a word at a time starts to win. */ +#define BYTE_CUTOFF 20 + +#if BYTE_CUTOFF < 3 + /* This must be at least at least this big, or some code later + on doesn't work. */ +# error "BYTE_CUTOFF is too small." +#endif + + if (n < BYTE_CUTOFF) + { + /* Strangely, this turns out to be the tightest way to write + this loop. */ + if (n != 0) + { + do + { + /* Strangely, combining these into one line performs worse. */ + *out8 = c; + out8++; + } + while (--n != 0); + } + + return s; + } + + /* Align 'out8'. We know n >= 3 so this won't write past the end. */ + while (((uintptr_t) out8 & 3) != 0) + { + *out8++ = c; + --n; + } + + /* Align 'n'. */ + while (n & 3) + out8[--n] = c; + + out32 = (uint32_t *) out8; + n32 = n >> 2; + + /* Tile input byte out to 32 bits. */ + v16 = __insn_intlb (c, c); + v32 = __insn_intlh (v16, v16); + + /* This must be at least 8 or the following loop doesn't work. */ +#define CACHE_LINE_SIZE_IN_WORDS (CHIP_L2_LINE_SIZE() / 4) + + /* Determine how many words we need to emit before the 'out32' + pointer becomes aligned modulo the cache line size. */ + to_align32 = (-((uintptr_t) out32 >> 2)) & (CACHE_LINE_SIZE_IN_WORDS - 1); + + /* Only bother aligning and using wh64 if there is at least one full + cache line to process. This check also prevents overrunning the + end of the buffer with alignment words. */ + if (to_align32 <= n32 - CACHE_LINE_SIZE_IN_WORDS) + { + int lines_left; + + /* Align out32 mod the cache line size so we can use wh64. */ + n32 -= to_align32; + for (; to_align32 != 0; to_align32--) + { + *out32 = v32; + out32++; + } + + /* Use unsigned divide to turn this into a right shift. */ + lines_left = (unsigned) n32 / CACHE_LINE_SIZE_IN_WORDS; + + do + { + /* Only wh64 a few lines at a time, so we don't exceed the + maximum number of victim lines. */ + int x = ((lines_left < CHIP_MAX_OUTSTANDING_VICTIMS ())? lines_left + : CHIP_MAX_OUTSTANDING_VICTIMS ()); + uint32_t *wh = out32; + int i = x; + int j; + + lines_left -= x; + + do + { + __insn_wh64 (wh); + wh += CACHE_LINE_SIZE_IN_WORDS; + } + while (--i); + + for (j = x * (CACHE_LINE_SIZE_IN_WORDS / 4); j != 0; j--) + { + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + *out32++ = v32; + } + } + while (lines_left != 0); + + /* We processed all full lines above, so only this many words + remain to be processed. */ + n32 &= CACHE_LINE_SIZE_IN_WORDS - 1; + } + + /* Now handle any leftover values. */ + if (n32 != 0) + { + do + { + *out32 = v32; + out32++; + } + while (--n32 != 0); + } + + return s; +} +weak_alias (__memset, memset) +libc_hidden_builtin_def (memset) diff --git a/sysdeps/tile/tilepro/memusage.h b/sysdeps/tile/tilepro/memusage.h new file mode 100644 index 0000000000..700c08b700 --- /dev/null +++ b/sysdeps/tile/tilepro/memusage.h @@ -0,0 +1,30 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define GETSP() ({ register uintptr_t stack_ptr asm ("sp"); stack_ptr; }) + +#define GETTIME(low,high) \ + { \ + low = __insn_mfspr (SPR_CYCLE_LOW); \ + high = __insn_mfspr (SPR_CYCLE_HIGH); \ + } + +#include diff --git a/sysdeps/tile/tilepro/rawmemchr.c b/sysdeps/tile/tilepro/rawmemchr.c new file mode 100644 index 0000000000..c1a58ec1fd --- /dev/null +++ b/sysdeps/tile/tilepro/rawmemchr.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +void * +__rawmemchr (const void *s, int c) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint32_t *p = (const uint32_t *) (s_int & -4); + + /* Create four copies of the byte for which we are looking. */ + const uint32_t goal = 0x01010101 * (uint8_t) c; + + /* Read the first word, but munge it so that bytes before the array + will not match goal. Note that this shift count expression works + because we know shift counts are taken mod 32. */ + const uint32_t before_mask = (1 << (s_int << 3)) - 1; + uint32_t v = (*p | before_mask) ^ (goal & before_mask); + + uint32_t bits; + while ((bits = __insn_seqb (v, goal)) == 0) + v = *++p; + + return ((char *) p) + (__insn_ctz (bits) >> 3); +} +libc_hidden_def (__rawmemchr) +weak_alias (__rawmemchr, rawmemchr) diff --git a/sysdeps/tile/tilepro/strchr.c b/sysdeps/tile/tilepro/strchr.c new file mode 100644 index 0000000000..e116ea9c55 --- /dev/null +++ b/sysdeps/tile/tilepro/strchr.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#undef strchr + +char * +strchr (const char *s, int c) +{ + int z, g; + + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint32_t *p = (const uint32_t *) (s_int & -4); + + /* Create four copies of the byte for which we are looking. */ + const uint32_t goal = 0x01010101 * (uint8_t) c; + + /* Read the first aligned word, but force bytes before the string to + match neither zero nor goal (we make sure the high bit of each + byte is 1, and the low 7 bits are all the opposite of the goal + byte). Note that this shift count expression works because we + know shift counts are taken mod 32. */ + const uint32_t before_mask = (1 << (s_int << 3)) - 1; + uint32_t v = (*p | before_mask) ^ (goal & __insn_shrib (before_mask, 1)); + + uint32_t zero_matches, goal_matches; + while (1) + { + /* Look for a terminating '\0'. */ + zero_matches = __insn_seqb (v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_seqb (v, goal); + + if (__builtin_expect ((zero_matches | goal_matches) != 0, 0)) + break; + + v = *++p; + } + + z = __insn_ctz (zero_matches); + g = __insn_ctz (goal_matches); + + /* If we found c before '\0' we got a match. Note that if c == '\0' + then g == z, and we correctly return the address of the '\0' + rather than NULL. */ + return (g <= z) ? ((char *) p) + (g >> 3) : NULL; +} +weak_alias (strchr, index) +libc_hidden_builtin_def (strchr) diff --git a/sysdeps/tile/tilepro/strchrnul.c b/sysdeps/tile/tilepro/strchrnul.c new file mode 100644 index 0000000000..6e7bba9c0a --- /dev/null +++ b/sysdeps/tile/tilepro/strchrnul.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +char * +__strchrnul (const char *s, int c) +{ + int z, g; + + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint32_t *p = (const uint32_t *) (s_int & -4); + + /* Create four copies of the byte for which we are looking. */ + const uint32_t goal = 0x01010101 * (uint8_t) c; + + /* Read the first aligned word, but force bytes before the string to + match neither zero nor goal (we make sure the high bit of each + byte is 1, and the low 7 bits are all the opposite of the goal + byte). Note that this shift count expression works because we + know shift counts are taken mod 32. */ + const uint32_t before_mask = (1 << (s_int << 3)) - 1; + uint32_t v = (*p | before_mask) ^ (goal & __insn_shrib (before_mask, 1)); + + uint32_t zero_matches, goal_matches; + while (1) + { + /* Look for a terminating '\0'. */ + zero_matches = __insn_seqb (v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_seqb (v, goal); + + if (__builtin_expect ((zero_matches | goal_matches) != 0, 0)) + break; + + v = *++p; + } + + z = __insn_ctz (zero_matches); + g = __insn_ctz (goal_matches); + + /* Return a pointer to the NUL or goal, whichever is first. */ + if (z < g) + g = z; + return ((char *) p) + (g >> 3); +} +weak_alias (__strchrnul, strchrnul) diff --git a/sysdeps/tile/tilepro/strlen.c b/sysdeps/tile/tilepro/strlen.c new file mode 100644 index 0000000000..26120681ba --- /dev/null +++ b/sysdeps/tile/tilepro/strlen.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +size_t +strlen (const char *s) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint32_t *p = (const uint32_t *) (s_int & -4); + + /* Read the first word, but force bytes before the string to be nonzero. + This expression works because we know shift counts are taken mod 32. */ + uint32_t v = *p | ((1 << (s_int << 3)) - 1); + + uint32_t bits; + while ((bits = __insn_seqb (v, 0)) == 0) + v = *++p; + + return ((const char *) p) + (__insn_ctz (bits) >> 3) - s; +} +libc_hidden_builtin_def (strlen) diff --git a/sysdeps/tile/tilepro/strrchr.c b/sysdeps/tile/tilepro/strrchr.c new file mode 100644 index 0000000000..b91b02b349 --- /dev/null +++ b/sysdeps/tile/tilepro/strrchr.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +char * +strrchr (const char *s, int c) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint32_t *p = (const uint32_t *) (s_int & -4); + + /* Create four copies of the byte for which we are looking. */ + const uint32_t goal = 0x01010101 * (uint8_t) c; + + /* Read the first aligned word, but force bytes before the string to + match neither zero nor goal (we make sure the high bit of each + byte is 1, and the low 7 bits are all the opposite of the goal + byte). Note that this shift count expression works because we + know shift counts are taken mod 32. */ + const uint32_t before_mask = (1 << (s_int << 3)) - 1; + uint32_t v = (*p | before_mask) ^ (goal & __insn_shrib (before_mask, 1)); + const char *found = NULL; + uint32_t zero_matches, goal_matches; + while (1) + { + /* Look for a terminating '\0'. */ + zero_matches = __insn_seqb (v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_seqb (v, goal); + + /* If we found the goal, record the last offset. */ + if (__builtin_expect (goal_matches != 0, 0)) + { + if (__builtin_expect (zero_matches != 0, 0)) + { + /* Clear any goal after the first zero. */ + int first_nul = __insn_ctz (zero_matches); + /* The number of top bits we need to clear is + 32 - (first_nul + 8). */ + int shift_amt = (24 - first_nul); + goal_matches <<= shift_amt; + goal_matches >>= shift_amt; + } + if (__builtin_expect (goal_matches != 0, 1)) + found = ((char *) p) + 3 - (__insn_clz (goal_matches) >> 3); + } + + if (__builtin_expect (zero_matches != 0, 0)) + return (char *) found; + + v = *++p; + } +} +weak_alias (strrchr, rindex) +libc_hidden_builtin_def (strrchr) diff --git a/sysdeps/tile/tls-macros.h b/sysdeps/tile/tls-macros.h new file mode 100644 index 0000000000..807ccdb0b7 --- /dev/null +++ b/sysdeps/tile/tls-macros.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +#ifdef __tilegx__ +#define TLS_GD_REL "hw0_last_tls_gd" +#define TLS_IE_REL "hw0_last_tls_ie" +#define LD_TLS "ld_tls" +#else +#define TLS_GD_REL "tls_gd_lo16" +#define TLS_IE_REL "tls_ie_lo16" +#define LD_TLS "lw_tls" +#endif + +#define TLS_GD(x) \ + ({ \ + int *__retval; \ + extern char _GLOBAL_OFFSET_TABLE_[]; \ + \ + asm ("addli r0, %1, " TLS_GD_REL "(" #x ")\n\t" \ + "jal tls_gd_call(" #x ")\n\t" \ + "addi %0, r0, tls_gd_add(" #x ")" : \ + "=r" (__retval) : "r" (_GLOBAL_OFFSET_TABLE_) : \ + "r25", "r26", "r27", "r28", "r29"); \ + __retval; }) + +/* No special support for LD mode. */ +#define TLS_LD TLS_GD + +#define TLS_IE(x) \ + ({ \ + int *__retval; \ + extern char _GLOBAL_OFFSET_TABLE_[]; \ + \ + asm ("addli %0, %1, " TLS_IE_REL "(" #x ")\n\t" \ + LD_TLS " %0, %0, tls_ie_load(" #x ")\n\t" \ + "add %0, %0, tp" : \ + "=r" (__retval) : "r" (_GLOBAL_OFFSET_TABLE_)); \ + __retval; }) + +/* No special support for LE mode. */ +#define TLS_LE TLS_IE diff --git a/sysdeps/tile/tst-audit.h b/sysdeps/tile/tst-audit.h new file mode 100644 index 0000000000..fd4f3d6157 --- /dev/null +++ b/sysdeps/tile/tst-audit.h @@ -0,0 +1,24 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 pltenter la_tile_gnu_pltenter +#define pltexit la_tile_gnu_pltexit +#define La_regs La_tile_regs +#define La_retval La_tile_retval +#define int_retval lrv_reg[0] diff --git a/sysdeps/unix/sysv/linux/tile/Makefile b/sysdeps/unix/sysv/linux/tile/Makefile new file mode 100644 index 0000000000..0cbfdd0e39 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/Makefile @@ -0,0 +1,15 @@ +ifeq ($(subdir),misc) + +# provides something like x86 compatibility. +# New code should probably use instead. +sysdep_headers += sys/reg.h + +# MIPS-style cacheflush routine +sysdep_headers += sys/cachectl.h +sysdep_routines += cacheflush + +# Control dataplane properties of current thread. +sysdep_headers += sys/dataplane.h +sysdep_routines += set_dataplane + +endif diff --git a/sysdeps/unix/sysv/linux/tile/Versions b/sysdeps/unix/sysv/linux/tile/Versions new file mode 100644 index 0000000000..1df7518c78 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/Versions @@ -0,0 +1,11 @@ +libc { + GLIBC_2.12 { + _flush_cache; + cacheflush; + fallocate64; + set_dataplane; + } + GLIBC_PRIVATE { + __syscall_error; + } +} diff --git a/sysdeps/unix/sysv/linux/tile/bits/environments.h b/sysdeps/unix/sysv/linux/tile/bits/environments.h new file mode 100644 index 0000000000..f1835179f3 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/bits/environments.h @@ -0,0 +1,101 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 _UNISTD_H +# error "Never include this file directly. Use instead" +#endif + +#include + +/* This header should define the following symbols under the described + situations. A value `1' means that the model is always supported, + `-1' means it is never supported. Undefined means it cannot be + statically decided. + + _POSIX_V7_ILP32_OFF32 32bit int, long, pointers, and off_t type + _POSIX_V7_ILP32_OFFBIG 32bit int, long, and pointers and larger off_t type + + _POSIX_V7_LP64_OFF32 64bit long and pointers and 32bit off_t type + _POSIX_V7_LPBIG_OFFBIG 64bit long and pointers and large off_t type + + The macros _POSIX_V6_ILP32_OFF32, _POSIX_V6_ILP32_OFFBIG, + _POSIX_V6_LP64_OFF32, _POSIX_V6_LPBIG_OFFBIG, _XBS5_ILP32_OFF32, + _XBS5_ILP32_OFFBIG, _XBS5_LP64_OFF32, and _XBS5_LPBIG_OFFBIG were + used in previous versions of the Unix standard and are available + only for compatibility. +*/ + +#if __WORDSIZE == 64 + +/* Environments with 32-bit wide pointers are optionally provided. + Therefore following macros aren't defined: + # undef _POSIX_V7_ILP32_OFF32 + # undef _POSIX_V7_ILP32_OFFBIG + # undef _POSIX_V6_ILP32_OFF32 + # undef _POSIX_V6_ILP32_OFFBIG + # undef _XBS5_ILP32_OFF32 + # undef _XBS5_ILP32_OFFBIG + and users need to check at runtime. */ + +/* We also have no use (for now) for an environment with bigger pointers + and offsets. */ +# define _POSIX_V7_LPBIG_OFFBIG -1 +# define _POSIX_V6_LPBIG_OFFBIG -1 +# define _XBS5_LPBIG_OFFBIG -1 + +/* By default we have 64-bit wide `long int', pointers and `off_t'. */ +# define _POSIX_V7_LP64_OFF64 1 +# define _POSIX_V6_LP64_OFF64 1 +# define _XBS5_LP64_OFF64 1 + +#else /* __WORDSIZE == 32 */ + +/* By default we have 32-bit wide `int', `long int', pointers and `off_t' + and all platforms support LFS. */ +# define _POSIX_V7_ILP32_OFF32 1 +# define _POSIX_V7_ILP32_OFFBIG 1 +# define _POSIX_V6_ILP32_OFF32 1 +# define _POSIX_V6_ILP32_OFFBIG 1 +# define _XBS5_ILP32_OFF32 1 +# define _XBS5_ILP32_OFFBIG 1 + +/* We optionally provide an environment with the above size but an 64-bit + side `off_t'. Therefore we don't define _POSIX_V7_ILP32_OFFBIG. */ + +/* Environments with 64-bit wide pointers can be provided, + so these macros aren't defined: + # undef _POSIX_V7_LP64_OFF64 + # undef _POSIX_V7_LPBIG_OFFBIG + # undef _POSIX_V6_LP64_OFF64 + # undef _POSIX_V6_LPBIG_OFFBIG + # undef _XBS5_LP64_OFF64 + # undef _XBS5_LPBIG_OFFBIG + and sysconf tests for it at runtime. */ + +#endif /* __WORDSIZE == 32 */ + +#ifdef __tilegx__ +/* Only TILE-Gx has the ability to choose 32- or 64-bit. */ +#define __ILP32_OFF32_CFLAGS "-m32" +#define __ILP32_OFFBIG_CFLAGS "-m32 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" +#define __ILP32_OFF32_LDFLAGS "-m32" +#define __ILP32_OFFBIG_LDFLAGS "-m32" +#define __LP64_OFF64_CFLAGS "-m64" +#define __LP64_OFF64_LDFLAGS "-m64" +#endif diff --git a/sysdeps/unix/sysv/linux/tile/bits/local_lim.h b/sysdeps/unix/sysv/linux/tile/bits/local_lim.h new file mode 100644 index 0000000000..6eb45c998d --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/bits/local_lim.h @@ -0,0 +1,101 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif +#ifndef ARG_MAX +# define __undef_ARG_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif +/* Have to remove ARG_MAX? */ +#ifdef __undef_ARG_MAX +# undef ARG_MAX +# undef __undef_ARG_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* We have no predefined limit on the number of threads. */ +#undef PTHREAD_THREADS_MAX + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. At least two pages for systems with 64k + pages. */ +#define PTHREAD_STACK_MIN 131072 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) diff --git a/sysdeps/unix/sysv/linux/tile/bits/mman.h b/sysdeps/unix/sysv/linux/tile/bits/mman.h new file mode 100644 index 0000000000..35863af458 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/bits/mman.h @@ -0,0 +1,110 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +#ifdef __USE_MISC +/* These are Linux-specific. */ +# define MAP_NONBLOCK 0x00080 /* Do not block on IO. */ +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_STACK MAP_GROWSDOWN /* Provide convenience alias. */ +# define MAP_LOCKED 0x00200 /* Lock the mapping. */ +# define MAP_NORESERVE 0x00400 /* Don't check for reservations. */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_POPULATE 0x00040 /* Populate (prefault) pagetables. */ +# define MAP_HUGETLB 0x04000 /* Create huge page mapping. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +# define MADV_MERGEABLE 12 /* KSM may merge identical pages. */ +# define MADV_UNMERGEABLE 13 /* KSM may not merge identical pages. */ +# define MADV_HUGEPAGE 14 /* Worth backing with hugepages. */ +# define MADV_NOHUGEPAGE 15 /* Not worth backing with hugepages. */ +# define MADV_HWPOISON 100 /* Poison a page for testing. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/sysdeps/unix/sysv/linux/tile/bits/mman.h~ b/sysdeps/unix/sysv/linux/tile/bits/mman.h~ new file mode 100644 index 0000000000..cb010312e7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/bits/mman.h~ @@ -0,0 +1,173 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +#ifdef __USE_MISC +/* These are Linux-specific. */ +# define MAP_NONBLOCK 0x00080 /* Do not block on IO. */ +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_STACK MAP_GROWSDOWN /* Provide convenience alias. */ +# define MAP_LOCKED 0x00200 /* Lock the mapping. */ +# define MAP_NORESERVE 0x00400 /* Don't check for reservations. */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_POPULATE 0x00040 /* Populate (prefault) pagetables. */ +# define MAP_HUGETLB 0x04000 /* Create huge page mapping. */ +#endif + +/* Specify the "home cache" for the page explicitly. The home cache is + the cache of one particular "home" cpu, which is used as a coherence + point for normal cached operations. Normally the kernel chooses for + you, but you can use the MAP_CACHE_HOME_xxx flags to override. + + User code should not use any symbols with a leading "_" as they are + implementation specific and may change from release to release + without warning. */ + +/* Implementation details; do not use directly. */ +#define _MAP_CACHE_INCOHERENT 0x40000 +#define _MAP_CACHE_HOME 0x80000 +#define _MAP_CACHE_HOME_SHIFT 20 +#define _MAP_CACHE_HOME_MASK 0x3ff +#define _MAP_CACHE_MKHOME(n) \ + (_MAP_CACHE_HOME | (((n) & _MAP_CACHE_HOME_MASK) << _MAP_CACHE_HOME_SHIFT)) + +/* Set the home cache to the specified cpu. */ +#define MAP_CACHE_HOME(n) _MAP_CACHE_MKHOME(n) + +/* Set the home cache to the current cpu. */ +#define _MAP_CACHE_HOME_HERE (_MAP_CACHE_HOME_MASK - 0) +#define MAP_CACHE_HOME_HERE _MAP_CACHE_MKHOME(_MAP_CACHE_HOME_HERE) + +/* Request no on-chip home, i.e. read from memory. Invalid with PROT_WRITE. */ +#define _MAP_CACHE_HOME_NONE (_MAP_CACHE_HOME_MASK - 1) +#define MAP_CACHE_HOME_NONE _MAP_CACHE_MKHOME(_MAP_CACHE_HOME_NONE) + +/* Request no on-chip home, and allow incoherent PROT_WRITE mappings. */ +#define MAP_CACHE_INCOHERENT (_MAP_CACHE_INCOHERENT | MAP_CACHE_HOME_NONE) + +/* Force the system to choose a single home cache, on a cpu of its choice. */ +#define _MAP_CACHE_HOME_SINGLE (_MAP_CACHE_HOME_MASK - 2) +#define MAP_CACHE_HOME_SINGLE _MAP_CACHE_MKHOME(_MAP_CACHE_HOME_SINGLE) + +/* Create a mapping that follows the task when it migrates. */ +#define _MAP_CACHE_HOME_TASK (_MAP_CACHE_HOME_MASK - 3) +#define MAP_CACHE_HOME_TASK _MAP_CACHE_MKHOME(_MAP_CACHE_HOME_TASK) + +/* Create a hash-for-home mapping. */ +#define _MAP_CACHE_HOME_HASH (_MAP_CACHE_HOME_MASK - 4) +#define MAP_CACHE_HOME_HASH _MAP_CACHE_MKHOME(_MAP_CACHE_HOME_HASH) + +/* Specify local caching attributes for the mapping. Normally the kernel + chooses whether to use the local cache, but these flags can be used + to override the kernel. */ + +/* Disable use of local L2 (on tile64, true for any writable mapping). */ +#define MAP_CACHE_NO_L2 0x20000 + +/* Disable use of local L1 (on tile64, ignored; L1 is disabled with L2). */ +#define MAP_CACHE_NO_L1 0x08000 + +/* Convenience alias that should be used for forward compatibility. */ +#define MAP_CACHE_NO_LOCAL (MAP_CACHE_NO_L1 | MAP_CACHE_NO_L2) + +/* Convenience alias for direct-to-RAM mappings. */ +#define MAP_CACHE_NONE (MAP_CACHE_HOME_NONE | MAP_CACHE_NO_LOCAL) + +/* Arrange for this mapping to take priority in the cache. */ +#define MAP_CACHE_PRIORITY 0x02000 + +/* Environment variable that controls hash-for-home in user programs. */ +#define MAP_CACHE_HASH_ENV_VAR "LD_CACHE_HASH" + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +# define MADV_MERGEABLE 12 /* KSM may merge identical pages. */ +# define MADV_UNMERGEABLE 13 /* KSM may not merge identical pages. */ +# define MADV_HWPOISON 100 /* Poison a page for testing. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/sysdeps/unix/sysv/linux/tile/bits/sigaction.h b/sysdeps/unix/sysv/linux/tile/bits/sigaction.h new file mode 100644 index 0000000000..1696d7481a --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/bits/sigaction.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction + { + /* Signal handler. */ +#ifdef __USE_POSIX199309 + union + { + /* Used if SA_SIGINFO is not set. */ + __sighandler_t sa_handler; + /* Used if SA_SIGINFO is set. */ + void (*sa_sigaction) (int, siginfo_t *, void *); + } + __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + + /* Additional set of signals to be blocked. */ + __sigset_t sa_mask; + + /* Special flags. */ + int sa_flags; + + /* Restore handler. */ + void (*sa_restorer) (void); + }; + +/* Bits in `sa_flags'. */ +#define SA_NOCLDSTOP 1 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 2 /* Don't create zombie on child death. */ +#define SA_SIGINFO 4 /* Invoke signal-catching function with + three arguments instead of one. */ +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_NOPTRACE 0x02000000 /* Don't ptrace this signal. */ +# define SA_ONSTACK 0x08000000 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESTART 0x10000000 /* Restart syscall on signal return. */ +# define SA_NODEFER 0x40000000 /* Don't automatically block the signal when + its handler is being executed. */ +# define SA_RESETHAND 0x80000000 /* Reset to SIG_DFL on entry to handler. */ +#endif +#ifdef __USE_MISC +# define SA_INTERRUPT 0x20000000 /* Historical no-op. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NOMASK SA_NODEFER +# define SA_ONESHOT SA_RESETHAND +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_BLOCK 0 /* Block signals. */ +#define SIG_UNBLOCK 1 /* Unblock signals. */ +#define SIG_SETMASK 2 /* Set the set of blocked signals. */ diff --git a/sysdeps/unix/sysv/linux/tile/bits/siginfo.h b/sysdeps/unix/sysv/linux/tile/bits/siginfo.h new file mode 100644 index 0000000000..a6d1c21917 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/bits/siginfo.h @@ -0,0 +1,319 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +#if !defined _SIGNAL_H && !defined __need_siginfo_t \ + && !defined __need_sigevent_t +# error "Never include this file directly. Use instead" +#endif + +#include + +#if (!defined __have_sigval_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t \ + || defined __need_sigevent_t)) +# define __have_sigval_t 1 + +/* Type for data associated with a signal. */ +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +#endif + +#if (!defined __have_siginfo_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t)) +# define __have_siginfo_t 1 + +# define __SI_MAX_SIZE 128 +# if __WORDSIZE == 64 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3) +# endif + +typedef struct siginfo + { + int si_signo; /* Signal number. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int si_code; /* Signal code. */ + + union + { + int _pad[__SI_PAD_SIZE]; + + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; + + /* POSIX.1b timers. */ + struct + { + int si_tid; /* Timer ID. */ + int si_overrun; /* Overrun count. */ + sigval_t si_sigval; /* Signal value. */ + } _timer; + + /* POSIX.1b signals. */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + sigval_t si_sigval; /* Signal value. */ + } _rt; + + /* SIGCHLD. */ + struct + { + __pid_t si_pid; /* Which child. */ + __uid_t si_uid; /* Real user ID of sending process. */ + int si_status; /* Exit value or signal. */ + __clock_t si_utime; + __clock_t si_stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ + struct + { + void *si_addr; /* Faulting insn/memory ref. */ + int si_trapno; /* TRAP # which caused the signal */ + } _sigfault; + + /* SIGPOLL. */ + struct + { + long int si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + } _sifields; + } siginfo_t; + + +/* X/Open requires some more fields with fixed names. */ +# define si_pid _sifields._kill.si_pid +# define si_uid _sifields._kill.si_uid +# define si_timerid _sifields._timer.si_tid +# define si_overrun _sifields._timer.si_overrun +# define si_status _sifields._sigchld.si_status +# define si_utime _sifields._sigchld.si_utime +# define si_stime _sifields._sigchld.si_stime +# define si_value _sifields._rt.si_sigval +# define si_int _sifields._rt.si_sigval.sival_int +# define si_ptr _sifields._rt.si_sigval.sival_ptr +# define si_addr _sifields._sigfault.si_addr +# define si_trapno _sifields._sigfault.si_trapno +# define si_band _sifields._sigpoll.si_band +# define si_fd _sifields._sigpoll.si_fd + + +/* Values for `si_code'. Positive values are reserved for kernel-generated + signals. */ +enum +{ + SI_ASYNCNL = -60, /* Sent by asynch name lookup completion. */ +# define SI_ASYNCNL SI_ASYNCNL + SI_TKILL = -6, /* Sent by tkill. */ +# define SI_TKILL SI_TKILL + SI_SIGIO, /* Sent by queued SIGIO. */ +# define SI_SIGIO SI_SIGIO + SI_ASYNCIO, /* Sent by AIO completion. */ +# define SI_ASYNCIO SI_ASYNCIO + SI_MESGQ, /* Sent by real time mesq state change. */ +# define SI_MESGQ SI_MESGQ + SI_TIMER, /* Sent by timer expiration. */ +# define SI_TIMER SI_TIMER + SI_QUEUE, /* Sent by sigqueue. */ +# define SI_QUEUE SI_QUEUE + SI_USER, /* Sent by kill, sigsend, raise. */ +# define SI_USER SI_USER + SI_KERNEL = 0x80 /* Send by kernel. */ +#define SI_KERNEL SI_KERNEL +}; + + +/* `si_code' values for SIGILL signal. */ +enum +{ + ILL_ILLOPC = 1, /* Illegal opcode. */ +# define ILL_ILLOPC ILL_ILLOPC + ILL_ILLOPN, /* Illegal operand. */ +# define ILL_ILLOPN ILL_ILLOPN + ILL_ILLADR, /* Illegal addressing mode. */ +# define ILL_ILLADR ILL_ILLADR + ILL_ILLTRP, /* Illegal trap. */ +# define ILL_ILLTRP ILL_ILLTRP + ILL_PRVOPC, /* Privileged opcode. */ +# define ILL_PRVOPC ILL_PRVOPC + ILL_PRVREG, /* Privileged register. */ +# define ILL_PRVREG ILL_PRVREG + ILL_COPROC, /* Coprocessor error. */ +# define ILL_COPROC ILL_COPROC + ILL_BADSTK, /* Internal stack error. */ +# define ILL_BADSTK ILL_BADSTK + ILL_DBLFLT, /* Double fault. */ +# define ILL_DBLFLT ILL_DBLFLT + ILL_HARDWALL /* User networks hardwall violation. */ +# define ILL_HARDWALL ILL_HARDWALL +}; + +/* `si_code' values for SIGFPE signal. */ +enum +{ + FPE_INTDIV = 1, /* Integer divide by zero. */ +# define FPE_INTDIV FPE_INTDIV + FPE_INTOVF, /* Integer overflow. */ +# define FPE_INTOVF FPE_INTOVF + FPE_FLTDIV, /* Floating point divide by zero. */ +# define FPE_FLTDIV FPE_FLTDIV + FPE_FLTOVF, /* Floating point overflow. */ +# define FPE_FLTOVF FPE_FLTOVF + FPE_FLTUND, /* Floating point underflow. */ +# define FPE_FLTUND FPE_FLTUND + FPE_FLTRES, /* Floating point inexact result. */ +# define FPE_FLTRES FPE_FLTRES + FPE_FLTINV, /* Floating point invalid operation. */ +# define FPE_FLTINV FPE_FLTINV + FPE_FLTSUB /* Subscript out of range. */ +# define FPE_FLTSUB FPE_FLTSUB +}; + +/* `si_code' values for SIGSEGV signal. */ +enum +{ + SEGV_MAPERR = 1, /* Address not mapped to object. */ +# define SEGV_MAPERR SEGV_MAPERR + SEGV_ACCERR /* Invalid permissions for mapped object. */ +# define SEGV_ACCERR SEGV_ACCERR +}; + +/* `si_code' values for SIGBUS signal. */ +enum +{ + BUS_ADRALN = 1, /* Invalid address alignment. */ +# define BUS_ADRALN BUS_ADRALN + BUS_ADRERR, /* Non-existant physical address. */ +# define BUS_ADRERR BUS_ADRERR + BUS_OBJERR /* Object specific hardware error. */ +# define BUS_OBJERR BUS_OBJERR +}; + +/* `si_code' values for SIGTRAP signal. */ +enum +{ + TRAP_BRKPT = 1, /* Process breakpoint. */ +# define TRAP_BRKPT TRAP_BRKPT + TRAP_TRACE /* Process trace trap. */ +# define TRAP_TRACE TRAP_TRACE +}; + +/* `si_code' values for SIGCHLD signal. */ +enum +{ + CLD_EXITED = 1, /* Child has exited. */ +# define CLD_EXITED CLD_EXITED + CLD_KILLED, /* Child was killed. */ +# define CLD_KILLED CLD_KILLED + CLD_DUMPED, /* Child terminated abnormally. */ +# define CLD_DUMPED CLD_DUMPED + CLD_TRAPPED, /* Traced child has trapped. */ +# define CLD_TRAPPED CLD_TRAPPED + CLD_STOPPED, /* Child has stopped. */ +# define CLD_STOPPED CLD_STOPPED + CLD_CONTINUED /* Stopped child has continued. */ +# define CLD_CONTINUED CLD_CONTINUED +}; + +/* `si_code' values for SIGPOLL signal. */ +enum +{ + POLL_IN = 1, /* Data input available. */ +# define POLL_IN POLL_IN + POLL_OUT, /* Output buffers available. */ +# define POLL_OUT POLL_OUT + POLL_MSG, /* Input message available. */ +# define POLL_MSG POLL_MSG + POLL_ERR, /* I/O error. */ +# define POLL_ERR POLL_ERR + POLL_PRI, /* High priority input available. */ +# define POLL_PRI POLL_PRI + POLL_HUP /* Device disconnected. */ +# define POLL_HUP POLL_HUP +}; + +# undef __need_siginfo_t +#endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t). */ + + +#if (defined _SIGNAL_H || defined __need_sigevent_t) \ + && !defined __have_sigevent_t +# define __have_sigevent_t 1 + +/* Structure to transport application-defined values with signals. */ +# define __SIGEV_MAX_SIZE 64 +# if __WORDSIZE == 64 +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 3) +# endif + +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[__SIGEV_PAD_SIZE]; + + /* When SIGEV_SIGNAL and SIGEV_THREAD_ID set, LWP ID of the + thread to receive the signal. */ + __pid_t _tid; + + struct + { + void (*_function) (sigval_t); /* Function to start. */ + void *_attribute; /* Really pthread_attr_t. */ + } _sigev_thread; + } _sigev_un; + } sigevent_t; + +/* POSIX names to access some of the members. */ +# define sigev_notify_function _sigev_un._sigev_thread._function +# define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +/* `sigev_notify' values. */ +enum +{ + SIGEV_SIGNAL = 0, /* Notify via signal. */ +# define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_NONE, /* Other notification: meaningless. */ +# define SIGEV_NONE SIGEV_NONE + SIGEV_THREAD, /* Deliver via thread creation. */ +# define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID +}; + +#endif /* have _SIGNAL_H. */ diff --git a/sysdeps/unix/sysv/linux/tile/cacheflush.c b/sysdeps/unix/sysv/linux/tile/cacheflush.c new file mode 100644 index 0000000000..d23a6c5c53 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/cacheflush.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* Flush cache(s). */ +int +_flush_cache (char *addr, const int nbytes, const int op) +{ +#ifdef __NR_cacheflush + return INLINE_SYSCALL (cacheflush, 3, addr, nbytes, op); +#else + __set_errno (ENOSYS); + return -1; +#endif +} +weak_alias (_flush_cache, cacheflush) diff --git a/sysdeps/unix/sysv/linux/tile/configure b/sysdeps/unix/sysv/linux/tile/configure new file mode 100644 index 0000000000..88b5788481 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/configure @@ -0,0 +1,4 @@ +# This file is generated from configure.in by Autoconf. DO NOT EDIT! + # Local configure fragment for sysdeps/unix/sysv/linux/tile. + +arch_minimum_kernel=2.6.32 diff --git a/sysdeps/unix/sysv/linux/tile/configure.in b/sysdeps/unix/sysv/linux/tile/configure.in new file mode 100644 index 0000000000..b983e28be6 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/configure.in @@ -0,0 +1,4 @@ +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. +# Local configure fragment for sysdeps/unix/sysv/linux/tile. + +arch_minimum_kernel=2.6.32 diff --git a/sysdeps/unix/sysv/linux/tile/getcontext.S b/sysdeps/unix/sysv/linux/tile/getcontext.S new file mode 100644 index 0000000000..34bc7d8ca2 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/getcontext.S @@ -0,0 +1,96 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "ucontext_i.h" + +/* int getcontext (ucontext_t *ucp) */ + + .text +ENTRY (__getcontext) + FEEDBACK_ENTER(__getcontext) + + /* Save the callee-saved GPRs. There's no need to save the + caller-saved GPRs since the eventual setcontext() or + swapcontext() will assume those registers are all dead. + Save value "1" to uc_flags to later recognize getcontext(). */ + { movei r11, 1; ADDI_PTR r10, r0, UC_FLAGS_OFFSET } + { ST r10, r11; addli r10, r0, UC_REG(30) } + { ST r10, r30; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r31; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r32; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r33; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r34; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r35; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r36; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r37; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r38; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r39; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r40; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r41; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r42; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r43; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r44; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r45; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r46; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r47; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r48; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r49; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r50; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r51; ADDI_PTR r10, r10, REGSIZE } + { ST r10, r52; ADDI_PTR r10, r10, REGSIZE } + { ST r10, tp; ADDI_PTR r10, r10, REGSIZE } + { ST r10, sp; ADDI_PTR r10, r10, REGSIZE } + { ST r10, lr; ADDI_PTR r10, r10, REGSIZE } + lnk r11 /* Point PC at the "jrp lr" instruction. */ + addli r11, r11, .Lreturn - . + { ST r10, r11; ADDI_PTR r10, r10, REGSIZE } + mfspr r11, INTERRUPT_CRITICAL_SECTION + { + ST r10, r11 + movei r1, 0 + } + + /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG / 8) */ + { + movei r3, _NSIG / 8 + addli r2, r0, UC_SIGMASK_OFFSET + } + { + movei r0, SIG_BLOCK + moveli TREG_SYSCALL_NR_NAME, __NR_rt_sigprocmask + } + swint1 + BNEZ r1, .Lsyscall_error + +.Lreturn: + { + movei r0, 0 + jrp lr + } + +.Lsyscall_error: + j SYSCALL_ERROR_NAME + +END (__getcontext) +.hidden __getcontext + +weak_alias (__getcontext, getcontext) diff --git a/sysdeps/unix/sysv/linux/tile/kernel-features.h b/sysdeps/unix/sysv/linux/tile/kernel-features.h new file mode 100644 index 0000000000..d234922983 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/kernel-features.h @@ -0,0 +1,44 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + + +/* TILE glibc support starts with 2.6.36, guaranteeing many kernel features. */ +#define __ASSUME_NEW_GETRLIMIT_SYSCALL 1 +#define __ASSUME_TRUNCATE64_SYSCALL 1 +#define __ASSUME_MMAP2_SYSCALL 1 +#define __ASSUME_STAT64_SYSCALL 1 +#define __ASSUME_FCNTL64 1 +#define __ASSUME_CLONE_THREAD_FLAGS 1 +#define __ASSUME_TGKILL 1 +#define __ASSUME_UTIMES 1 +#define __ASSUME_FADVISE64_64_SYSCALL 1 +#define __ASSUME_O_CLOEXEC 1 +#define __ASSUME_SOCK_CLOEXEC 1 +#define __ASSUME_IN_NONBLOCK 1 +#define __ASSUME_PIPE2 1 +#define __ASSUME_EVENTFD2 1 +#define __ASSUME_SIGNALFD4 1 +#define __ASSUME_ACCEPT4 1 +#define __ASSUME_DUP3 1 + +#include_next + +/* Define this if your 32-bit syscall API requires 64-bit register + pairs to start with an even-number register. */ +#define __ASSUME_ALIGNED_REGISTER_PAIRS 1 diff --git a/sysdeps/unix/sysv/linux/tile/makecontext.c b/sysdeps/unix/sysv/linux/tile/makecontext.c new file mode 100644 index 0000000000..060cf74bc2 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/makecontext.c @@ -0,0 +1,68 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +void +__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) +{ + extern void __startcontext (void); + uint_reg_t *sp, *args; + va_list ap; + int i; + + /* Initialize the top of stack. */ + sp = (uint_reg_t *) ((((intptr_t) ucp->uc_stack.ss_sp + + ucp->uc_stack.ss_size) & -16L) - 16); + + /* Allow room for memory-passed arguments if necessary. */ + if (argc > 10) + sp -= 2 + (argc - 10); + + sp[0] = sp[1] = 0; + + /* Set parameters. */ + va_start (ap, argc); + args = &ucp->uc_mcontext.gregs[0]; + for (i = 0; i < argc; i++) + { + if (i == 10) + args = &sp[2]; + *args++ = va_arg (ap, long); + } + va_end (ap); + + /* Pass (*func) to __startcontext in pc. */ + ucp->uc_mcontext.pc = (long) func; + + /* Set stack pointer. */ + ucp->uc_mcontext.sp = (long) sp; + + /* Set the return address to trampoline. */ + ucp->uc_mcontext.lr = (long) __startcontext; + + /* Pass ucp->uc_link to __start_context in r30. */ + ucp->uc_mcontext.gregs[30] = (long) ucp->uc_link; +} +weak_alias (__makecontext, makecontext) diff --git a/sysdeps/unix/sysv/linux/tile/nptl/Makefile b/sysdeps/unix/sysv/linux/tile/nptl/Makefile new file mode 100644 index 0000000000..79e03546fc --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/Makefile @@ -0,0 +1,7 @@ +# pull in __syscall_error routine +libpthread-routines += sysdep + +ifeq ($(subdir),nptl) +# Avoid .cfi_startproc/endproc markers when creating init and fini pieces. +CFLAGS-pt-initfini.s += -fno-asynchronous-unwind-tables +endif diff --git a/sysdeps/unix/sysv/linux/tile/nptl/bits/pthreadtypes.h b/sysdeps/unix/sysv/linux/tile/nptl/bits/pthreadtypes.h new file mode 100644 index 0000000000..a71a4b77ec --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/bits/pthreadtypes.h @@ -0,0 +1,221 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on work contributed by Ulrich Drepper , 2002. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers. The structure of the attribute type is not + exposed on purpose. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +#if __WORDSIZE == 64 +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling. The structure of the attribute + type is not exposed on purpose. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; +#if __WORDSIZE == 64 + unsigned int __nusers; +#endif + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; +#if __WORDSIZE == 64 + int __spins; + __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV 1 +#else + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; +#endif + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is not exposed on purpose. */ +typedef union +{ +# if __WORDSIZE == 64 + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; +# else + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; + int __writer; + } __data; +# endif + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/sysdeps/unix/sysv/linux/tile/nptl/bits/semaphore.h b/sysdeps/unix/sysv/linux/tile/nptl/bits/semaphore.h new file mode 100644 index 0000000000..b1eca926ad --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/bits/semaphore.h @@ -0,0 +1,42 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + Based on work contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use directly; include instead." +#endif + +#include + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T 32 +#else +# define __SIZEOF_SEM_T 16 +#endif + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/sysdeps/unix/sysv/linux/tile/nptl/clone.S b/sysdeps/unix/sysv/linux/tile/nptl/clone.S new file mode 100644 index 0000000000..73a5e84617 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/clone.S @@ -0,0 +1,220 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after it's all over. */ + +#include +#define _ERRNO_H 1 +#include + +#include +#include +#include +#include + +/* What we save where in the stack frame; must include all callee-saves. */ +#define FRAME_NEXT_LR (0 * REGSIZE) /* reserved by ABI; not used here */ +#define FRAME_SP (1 * REGSIZE) +#define FRAME_R30 (2 * REGSIZE) +#define FRAME_R31 (3 * REGSIZE) +#define FRAME_R32 (4 * REGSIZE) +#define FRAME_SIZE (5 * REGSIZE) + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + pid_t *ptid, struct user_desc *tls, pid_t *ctid); */ + + .text +ENTRY (__clone) + /* sanity check arguments */ + BEQZ r0, .Linvalid + BEQZ r1, .Linvalid + + /* Create a stack frame so we can pass callee-saves to new task. */ + { + move r10, sp + ST sp, lr + ADDI_PTR sp, sp, -FRAME_SIZE + } + cfi_offset (lr, 0) + cfi_def_cfa_offset (FRAME_SIZE) + ADDI_PTR r11, sp, FRAME_SP + { + ST r11, r10 + ADDI_PTR r11, sp, FRAME_R30 + } + { + ST r11, r30 + ADDI_PTR r11, sp, FRAME_R31 + } + cfi_offset (r30, FRAME_R30 - FRAME_SIZE) + { + ST r11, r31 + ADDI_PTR r11, sp, FRAME_R32 + } + cfi_offset (r31, FRAME_R31 - FRAME_SIZE) + ST r11, r32 + cfi_offset (r32, FRAME_R32 - FRAME_SIZE) + + /* Make sure child stack is properly aligned, and set up the + top frame so that we can call out of it immediately in the + child. Setting it up here means we fault in the parent if + it's bogus, which is probably cleaner than faulting first + thing in the child. */ + ADDI_PTR r1, r1, -C_ABI_SAVE_AREA_SIZE + andi r1, r1, -C_ABI_SAVE_AREA_SIZE + ADDI_PTR r9, r1, REGSIZE /* sp of this frame on entry, i.e. zero */ + ST r9, zero + + /* We need to switch the argument convention around from + libc to kernel: + + libc: + r0 fn + r1 child_stack + r2 flags + r3 arg + r4 ptid + r5 tls + r6 ctid + + kernel: + r0 flags + r1 child_stack [same as libc] + r2 ptid + r3 ctid + r4 tls + + Plus the callee-saves as described at .Lthread_start, below. */ + { + move r32, r0 + move r0, r2 + } + { + move r31, r3 + move r3, r6 + } + { + move r30, r2 + move r2, r4 + } + { + move r4, r5 + moveli TREG_SYSCALL_NR_NAME, __NR_clone + } + swint1 + BEQZ r0, .Lthread_start /* If in child task. */ + + /* Restore the callee-saved registers and return. */ + ADDLI_PTR lr, sp, FRAME_SIZE + { + LD lr, lr + ADDLI_PTR r30, sp, FRAME_R30 + } + { + LD r30, r30 + ADDLI_PTR r31, sp, FRAME_R31 + } + { + LD r31, r31 + ADDLI_PTR r32, sp, FRAME_R32 + } + { + LD r32, r32 + ADDI_PTR sp, sp, FRAME_SIZE + } + cfi_def_cfa_offset (0) + + BNEZ r1, .Lerror + jrp lr + +.Lerror: + j SYSCALL_ERROR_NAME + +.Linvalid: + { + movei r1, EINVAL + j SYSCALL_ERROR_NAME + } + +/* This function expects to receive: + + sp: the top of a valid stack area + r30: clone() flags + r31: the argument to pass to the user function + r32: the user function pointer */ + +.Lthread_start: + /* Check and see if we need to reset the PID, which we do if + CLONE_THREAD isn't set, i.e. we're not staying in the thread group. + If CLONE_VM is set, we're doing some kind of thread-like clone, + so we set the tid/pid to -1 to disable using the cached values + in getpid(). Otherwise (if CLONE_VM isn't set), it's a + fork-like clone, and we go ahead and write the cached values + from the true system pid (retrieved via __NR_getpid syscall). */ +#ifdef __tilegx__ + { + moveli r0, hw1_last(CLONE_VM) + moveli r1, hw1_last(CLONE_THREAD) + } + { + shl16insli r0, r0, hw0(CLONE_VM) + shl16insli r1, r1, hw0(CLONE_THREAD) + } +#else + { + moveli r0, lo16(CLONE_VM) + moveli r1, lo16(CLONE_THREAD) + } + { + auli r0, r0, ha16(CLONE_VM) + auli r1, r1, ha16(CLONE_THREAD) + } +#endif + { + and r0, r30, r0 + and r1, r30, r1 + } + BNEZ r1, .Lno_reset_pid /* CLONE_THREAD is set */ + { + movei r0, -1 + BNEZ r0, .Lgotpid /* CLONE_VM is set */ + } + moveli TREG_SYSCALL_NR_NAME, __NR_getpid + swint1 +.Lgotpid: + ADDLI_PTR r2, tp, PID_OFFSET + { + ST4 r2, r0 + ADDLI_PTR r2, tp, TID_OFFSET + } + ST4 r2, r0 +.Lno_reset_pid: + { + /* Invoke user function with specified argument. */ + move r0, r31 + jalr r32 + } + { + j HIDDEN_JUMPTARGET(_exit) + info INFO_OP_CANNOT_BACKTRACE /* Notify backtracer to stop. */ + } +PSEUDO_END (__clone) + +weak_alias (__clone, clone) diff --git a/sysdeps/unix/sysv/linux/tile/nptl/createthread.c b/sysdeps/unix/sysv/linux/tile/nptl/createthread.c new file mode 100644 index 0000000000..816316b1d8 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/createthread.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE ((void *) (pd) \ + + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +/* Get the real implementation. */ +#include diff --git a/sysdeps/unix/sysv/linux/tile/nptl/fork.c b/sysdeps/unix/sysv/linux/tile/nptl/fork.c new file mode 100644 index 0000000000..4267fa48e4 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/fork.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + Based on work contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 4, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, \ + 0, NULL, &THREAD_SELF->tid) + +#include diff --git a/sysdeps/unix/sysv/linux/tile/nptl/lowlevellock.h b/sysdeps/unix/sysv/linux/tile/nptl/lowlevellock.h new file mode 100644 index 0000000000..55bddd5ba8 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/lowlevellock.h @@ -0,0 +1,281 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include +#include +#include +#include +#include +#include + + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait (futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1, private); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + + + +static inline int __attribute__ ((always_inline)) +__lll_trylock (int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0; +} +#define lll_trylock(lock) __lll_trylock (&(lock)) + + +static inline int __attribute__ ((always_inline)) +__lll_cond_trylock (int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; +} +#define lll_cond_trylock(lock) __lll_cond_trylock (&(lock)) + + +static inline int __attribute__ ((always_inline)) +__lll_robust_trylock (int *futex, int id) +{ + return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0; +} +#define lll_robust_trylock(lock, id) \ + __lll_robust_trylock (&(lock), id) + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +static inline void __attribute__ ((always_inline)) +__lll_lock (int *futex, int private) +{ + if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) + { + if (__builtin_constant_p (private) && private == LLL_PRIVATE) + __lll_lock_wait_private (futex); + else + __lll_lock_wait (futex, private); + } +} +#define lll_lock(futex, private) __lll_lock (&(futex), private) + + +static inline int __attribute__ ((always_inline)) +__lll_robust_lock (int *futex, int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_lock_wait (futex, private); + return result; +} +#define lll_robust_lock(futex, id, private) \ + __lll_robust_lock (&(futex), id, private) + + +static inline void __attribute__ ((always_inline)) +__lll_cond_lock (int *futex, int private) +{ + if (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0) + __lll_lock_wait (futex, private); +} +#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) + + +#define lll_robust_cond_lock(futex, id, private) \ + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; + +static inline int __attribute__ ((always_inline)) +__lll_timedlock (int *futex, const struct timespec *abstime, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) + result = __lll_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_timedlock(futex, abstime, private) \ + __lll_timedlock (&(futex), abstime, private) + + +static inline int __attribute__ ((always_inline)) +__lll_robust_timedlock (int *futex, const struct timespec *abstime, + int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_robust_timedlock(futex, abstime, id, private) \ + __lll_robust_timedlock (&(futex), abstime, id, private) + + +#define __lll_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_unlock(futex, private) __lll_unlock(&(futex), private) + + +#define __lll_robust_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_robust_unlock(futex, private) \ + __lll_robust_unlock(&(futex), private) + + +#define lll_islocked(futex) \ + (futex != 0) + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ + } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */ diff --git a/sysdeps/unix/sysv/linux/tile/nptl/pt-vfork.S b/sysdeps/unix/sysv/linux/tile/nptl/pt-vfork.S new file mode 100644 index 0000000000..a6ccb1f51f --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/pt-vfork.S @@ -0,0 +1,2 @@ +#define PT_VFORK 1 /* pid is never zero */ +#include "vfork.S" diff --git a/sysdeps/unix/sysv/linux/tile/nptl/pthread_once.c b/sysdeps/unix/sysv/linux/tile/nptl/pthread_once.c new file mode 100644 index 0000000000..1272be0dab --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/pthread_once.c @@ -0,0 +1,95 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + Based on work contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +unsigned long int __fork_generation attribute_hidden; + + +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + + +int +__pthread_once (once_control, init_routine) + pthread_once_t *once_control; + void (*init_routine) (void); +{ + while (1) + { + int oldval, val, newval; + + val = *once_control; + do + { + /* Check if the initialized has already been done. */ + if ((val & 2) != 0) + return 0; + + oldval = val; + newval = (oldval & 3) | __fork_generation | 1; + val = atomic_compare_and_exchange_val_acq (once_control, newval, + oldval); + } + while (__builtin_expect (val != oldval, 0)); + + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) != 0) + { + /* Check whether the initializer execution was interrupted + by a fork. */ + if (((oldval ^ newval) & -4) == 0) + { + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, newval, LLL_PRIVATE); + continue; + } + } + + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + + /* Add one to *once_control. */ + atomic_increment (once_control); + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + break; + } + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/sysdeps/unix/sysv/linux/tile/nptl/sysdep-cancel.h b/sysdeps/unix/sysv/linux/tile/nptl/sysdep-cancel.h new file mode 100644 index 0000000000..e00ea50a7b --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/sysdep-cancel.h @@ -0,0 +1,155 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +/* Allow hacking in some extra code if desired. */ +#ifndef PSEUDO_EXTRA +#define PSEUDO_EXTRA +#endif + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + ENTRY(__##syscall_name##_nocancel); \ + PSEUDO_EXTRA \ + moveli TREG_SYSCALL_NR_NAME, SYS_ify(syscall_name); \ + swint1; \ + BNEZ r1, 0f; \ + jrp lr; \ + END(__##syscall_name##_nocancel); \ + ENTRY (name) \ + SINGLE_THREAD_P(r11); \ + BEQZ r11, L(pseudo_cancel); \ + PSEUDO_EXTRA \ + moveli TREG_SYSCALL_NR_NAME, SYS_ify(syscall_name); \ + swint1; \ + BNEZ r1, 0f; \ + jrp lr; \ + L(pseudo_cancel): \ + { \ + move r11, sp; \ + ST sp, lr; \ + ADDI_PTR sp, sp, -STKSPACE; \ + }; \ + cfi_offset (lr, 0); \ + cfi_def_cfa_offset (STKSPACE); \ + { \ + ADDI_PTR r12, sp, REGSIZE; \ + ADDI_PTR r13, sp, 2 * REGSIZE; /* set up for PUSHARGS_0 */ \ + }; \ + ST r12, r11; \ + PUSHARGS_##args /* save syscall args */ \ + CENABLE; \ + ADDI_PTR r12, sp, 10 * REGSIZE; \ + { \ + ST r12, r0; /* save mask */ \ + ADDI_PTR r13, sp, 2 * REGSIZE; /* set up for POPARGS_0 */ \ + }; \ + POPARGS_##args /* restore syscall args */ \ + PSEUDO_EXTRA \ + moveli TREG_SYSCALL_NR_NAME, SYS_ify(syscall_name); \ + swint1; \ + ADDI_PTR r12, sp, 12 * REGSIZE; \ + { \ + ST r12, r1; /* save syscall result */ \ + ADDI_PTR r12, sp, 11 * REGSIZE; \ + }; \ + { \ + ST r12, r0; \ + ADDI_PTR r13, sp, 10 * REGSIZE; \ + }; \ + LD r0, r13; /* pass mask as arg1 */ \ + CDISABLE; \ + { \ + ADDI_PTR lr, sp, STKSPACE; \ + ADDI_PTR r0, sp, 11 * REGSIZE; \ + }; \ + { \ + LD r0, r0; \ + ADDI_PTR r1, sp, 12 * REGSIZE; \ + }; \ + LD r1, r1; \ + { \ + LD lr, lr; \ + ADDI_PTR sp, sp, STKSPACE; \ + }; \ + cfi_def_cfa_offset (0); \ + BNEZ r1, 0f + +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 { ADDI_PTR r14, sp, 3 * REGSIZE; ST r13, r0 }; +# define PUSHARGS_2 PUSHARGS_1 { ADDI_PTR r13, sp, 4 * REGSIZE; ST r14, r1 }; +# define PUSHARGS_3 PUSHARGS_2 { ADDI_PTR r14, sp, 5 * REGSIZE; ST r13, r2 }; +# define PUSHARGS_4 PUSHARGS_3 { ADDI_PTR r13, sp, 6 * REGSIZE; ST r14, r3 }; +# define PUSHARGS_5 PUSHARGS_4 { ADDI_PTR r14, sp, 7 * REGSIZE; ST r13, r4 }; +# define PUSHARGS_6 PUSHARGS_5 { ADDI_PTR r13, sp, 8 * REGSIZE; ST r14, r5 }; +# define PUSHARGS_7 PUSHARGS_6 { ADDI_PTR r14, sp, 9 * REGSIZE; ST r13, r6 }; + +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 { ADDI_PTR r14, sp, 3 * REGSIZE; LD r0, r13 }; +# define POPARGS_2 POPARGS_1 { ADDI_PTR r13, sp, 4 * REGSIZE; LD r1, r14 }; +# define POPARGS_3 POPARGS_2 { ADDI_PTR r14, sp, 5 * REGSIZE; LD r2, r13 }; +# define POPARGS_4 POPARGS_3 { ADDI_PTR r13, sp, 6 * REGSIZE; LD r3, r14 }; +# define POPARGS_5 POPARGS_4 { ADDI_PTR r14, sp, 7 * REGSIZE; LD r4, r13 }; +# define POPARGS_6 POPARGS_5 { ADDI_PTR r13, sp, 8 * REGSIZE; LD r5, r14 }; +# define POPARGS_7 POPARGS_6 { ADDI_PTR r14, sp, 9 * REGSIZE; LD r6, r13 }; + +# define STKSPACE (13 * REGSIZE) + +# ifdef IS_IN_libpthread +# define CENABLE jal __pthread_enable_asynccancel +# define CDISABLE jal __pthread_disable_asynccancel +# elif defined IS_IN_librt +# define CENABLE jal __librt_enable_asynccancel +# define CDISABLE jal __librt_disable_asynccancel +# else +# define CENABLE jal __libc_enable_asynccancel +# define CDISABLE jal __libc_disable_asynccancel +# endif + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) \ + == 0, 1) +# else +# define SINGLE_THREAD_P(reg) \ + ADDLI_PTR reg, tp, MULTIPLE_THREADS_OFFSET; \ + LD reg, reg; \ + CMPEQI reg, reg, 0 +#endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P 1 +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/sysdeps/unix/sysv/linux/tile/nptl/vfork.S b/sysdeps/unix/sysv/linux/tile/nptl/vfork.S new file mode 100644 index 0000000000..ed581ae864 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/vfork.S @@ -0,0 +1,81 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define __ASSEMBLY__ /* for kernel headers */ +#include +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + + .text +ENTRY (__vfork) + { + addli r11, tp, PID_OFFSET /* Point at PID. */ + movei r13, 1 + } + { + LD4U r12, r11 /* Load the saved PID. */ + shli r13, r13, 31 /* Build 0x80000000. */ + } + sub r12, zero, r12 /* Negate it. */ +#ifndef PT_VFORK + CMOVEQZ r12, r12, r13 /* Replace zero pids. */ +#endif + ST4 r11, r12 /* Store the temporary PID. */ + + { + moveli r0, CLONE_VFORK | CLONE_VM | SIGCHLD + move r1, zero + } + { + move r2, zero + move r3, zero + } + moveli TREG_SYSCALL_NR_NAME, __NR_clone + swint1 + + BEQZ r0, 1f /* If we are the parent... */ + { + addli r11, tp, PID_OFFSET /* Point at PID. */ + movei r13, 1 + } + { + LD4U r12, r11 /* Load the saved PID. */ + shli r13, r13, 31 /* Build 0x80000000. */ + } + { + CMPEQ r13, r12, r12 /* Test for that value. */ + sub r12, zero, r12 /* Re-negate it. */ + } +#ifndef PT_VFORK + CMOVNEZ r12, r13, zero /* Replace zero pids. */ +#endif + ST4 r11, r12 /* Restore the PID. */ +1: + BNEZ r1, 0f + jrp lr +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/sysdeps/unix/sysv/linux/tile/nptl/waitpid.S b/sysdeps/unix/sysv/linux/tile/nptl/waitpid.S new file mode 100644 index 0000000000..9aa793e12b --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/nptl/waitpid.S @@ -0,0 +1,20 @@ +/* +extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +/* Call __NR_wait4, providing fourth argument (struct rusage *) as NULL. */ +#define PSEUDO_EXTRA move r3, zero; +#include + +PSEUDO (__waitpid, wait4, 3) +ret +PSEUDO_END(__waitpid) + +libc_hidden_def (__waitpid) +weak_alias (__waitpid, waitpid) +libc_hidden_weak (waitpid) +weak_alias (__waitpid, __libc_waitpid) +libc_hidden_weak (__libc_waitpid) + +#endif diff --git a/sysdeps/unix/sysv/linux/tile/profil-counter.h b/sysdeps/unix/sysv/linux/tile/profil-counter.h new file mode 100644 index 0000000000..38cecedcc5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/profil-counter.h @@ -0,0 +1,27 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +static void +profil_counter (int signo, SIGCONTEXT scp) +{ + profil_count ((void *) GET_PC (scp)); +} diff --git a/sysdeps/unix/sysv/linux/tile/set_dataplane.c b/sysdeps/unix/sysv/linux/tile/set_dataplane.c new file mode 100644 index 0000000000..5e82a23357 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/set_dataplane.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#ifdef __NR_set_dataplane +#include +#endif + +/* Request dataplane modes from the kernel. */ +int +set_dataplane (int flags) +{ +#ifdef __NR_set_dataplane + return INLINE_SYSCALL (set_dataplane, 1, flags); +#else + __set_errno (ENOSYS); + return -1; +#endif +} diff --git a/sysdeps/unix/sysv/linux/tile/setcontext.S b/sysdeps/unix/sysv/linux/tile/setcontext.S new file mode 100644 index 0000000000..6c22bbdac9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/setcontext.S @@ -0,0 +1,202 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include "ucontext_i.h" + +/* PL to return to via iret in setcontext */ +#define RETURN_PL 0 + +/* int setcontext (const ucontext_t *ucp) */ + + .text +ENTRY (__setcontext) + FEEDBACK_ENTER(__setcontext) + + /* See if this is a true signal context (flags == 0). + If so, restore by invoking rt_sigreturn(). */ +#if UC_FLAGS_OFFSET != 0 +# error "Add offset to r0 prior to load." +#endif + LD r10, r0 + { + BEQZ r10, .Lsigreturn + addi r10, r10, -1 /* Confirm that it has value "1". */ + } + BNEZ r10, .Lbadcontext + + /* Save lr and r0 briefly on the stack and set the signal mask: + rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG / 8). */ + { + ST sp, lr + ADDI_PTR r11, sp, -(2 * REGSIZE) + move r10, sp + } + cfi_offset (lr, 0) + { + ST r11, r10 + ADDI_PTR r10, sp, -REGSIZE + ADDI_PTR sp, sp, -(3 * REGSIZE) + } + cfi_def_cfa_offset (3 * REGSIZE) + { + ST r10, r0 + ADDLI_PTR r1, r0, UC_SIGMASK_OFFSET + } + cfi_offset (r0, -REGSIZE) + { + movei r3, _NSIG / 8 + movei r2, 0 + } + { + movei r0, SIG_SETMASK + moveli TREG_SYSCALL_NR_NAME, __NR_rt_sigprocmask + } + swint1 + { + ADDI_PTR sp, sp, 3 * REGSIZE + ADDI_PTR r11, sp, 2 * REGSIZE /* Restore uc_context to r11. */ + } + cfi_def_cfa_offset (0) + LD lr, sp + LD r11, r11 + { + ADDI_PTR r10, r11, UC_REG(0) + BNEZ r1, .Lsyscall_error + } + + /* Restore the argument registers; note they will be random + unless makecontext() has been called. */ + { LD r0, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r1, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r2, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r3, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r4, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r5, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r6, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r7, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r8, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r9, r10; ADDLI_PTR r10, r10, UC_REG(30) - UC_REG(9) } + + /* Restore the callee-saved GPRs. */ + { LD r30, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r31, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r32, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r33, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r34, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r35, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r36, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r37, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r38, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r39, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r40, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r41, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r42, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r43, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r44, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r45, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r46, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r47, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r48, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r49, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r50, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r51, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r52, r10; ADDI_PTR r10, r10, REGSIZE * 2 } + /* Skip tp since it must not change for a given thread. */ + { LD sp, r10; ADDI_PTR r10, r10, REGSIZE } + { LD lr, r10; ADDI_PTR r10, r10, REGSIZE } + { LD r11, r10; ADDI_PTR r10, r10, REGSIZE } + + /* Construct an iret context; we set ICS so we can validly load + EX_CONTEXT for iret without being interrupted halfway through. */ + { + LD r12, r10 + movei r13, 1 + } + { + mtspr INTERRUPT_CRITICAL_SECTION, r13 + shli r12, r12, SPR_EX_CONTEXT_0_1__ICS_SHIFT + } + { + mtspr EX_CONTEXT_0_0, r11 + ori r12, r12, RETURN_PL + } + mtspr EX_CONTEXT_0_1, r12 + iret + jrp lr /* keep the backtracer happy */ + +.Lsigreturn: + /* This is a context obtained from a signal handler. + Perform a full restore by pushing the context + passed onto a simulated signal frame on the stack + and call the signal return syscall as if a signal + handler exited normally. */ + { + ADDLI_PTR sp, sp, -(C_ABI_SAVE_AREA_SIZE + SI_MAX_SIZE + UC_SIZE) + ADDLI_PTR r1, sp, -UC_SIZE + } + cfi_def_cfa_offset (C_ABI_SAVE_AREA_SIZE + SI_MAX_SIZE + UC_SIZE) + moveli r2, UC_SIZE / REGSIZE +0: { + LD r10, r0 + ADDI_PTR r0, r0, REGSIZE + } + { + ST r1, r10 + ADDI_PTR r1, r1, REGSIZE + addi r2, r2, -1 + } + BNEZ r2, 0b + moveli TREG_SYSCALL_NR_NAME, __NR_rt_sigreturn + swint1 + + /* Restore the stack and fall through to the error + path. Successful rt_sigreturn never returns to + its calling place. */ + ADDLI_PTR sp, sp, (C_ABI_SAVE_AREA_SIZE + SI_MAX_SIZE + UC_SIZE) + cfi_def_cfa_offset (0) + +.Lsyscall_error: + j SYSCALL_ERROR_NAME + +.Lbadcontext: + { + movei r1, EINVAL + j SYSCALL_ERROR_NAME + } + +END (__setcontext) + +.hidden __setcontext +weak_alias (__setcontext, setcontext) + +ENTRY (__startcontext) + FEEDBACK_ENTER(__startcontext) + BEQZ r30, 1f + { + move r0, r30 + jal __setcontext + } +1: j HIDDEN_JUMPTARGET(exit) +END (__startcontext) +.hidden __startcontext diff --git a/sysdeps/unix/sysv/linux/tile/sigcontextinfo.h b/sysdeps/unix/sysv/linux/tile/sigcontextinfo.h new file mode 100644 index 0000000000..fe700eaff4 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/sigcontextinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define SIGCONTEXT siginfo_t *_si, struct ucontext * +#define SIGCONTEXT_EXTRA_ARGS _si, +#define GET_PC(ctx) ((void *) (long) ctx->uc_mcontext.pc) +#define GET_FRAME(ctx) ((void *) (long) ctx->uc_mcontext.regs[TREG_FP]) +#define GET_STACK(ctx) ((void *) (long) ctx->uc_mcontext.sp) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/sysdeps/unix/sysv/linux/tile/swapcontext.S b/sysdeps/unix/sysv/linux/tile/swapcontext.S new file mode 100644 index 0000000000..95d3afa827 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/swapcontext.S @@ -0,0 +1,87 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "ucontext_i.h" + +/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ + + .text +ENTRY (__swapcontext) + FEEDBACK_ENTER(__swapcontext) + /* Set up a frame and save r0 and r1. */ + { + ST sp, lr + ADDI_PTR r11, sp, -(3 * REGSIZE) + move r10, sp + } + cfi_offset (lr, 0) + { + ST r11, r10 + ADDI_PTR r10, sp, -(2 * REGSIZE) + } + { + ST r10, r0 + ADDI_PTR r10, sp, -REGSIZE + ADDI_PTR sp, sp, -(4 * REGSIZE) + } + cfi_def_cfa_offset (4 * REGSIZE) + ST r10, r1 + + /* Save the current context. */ + jal __getcontext + + /* Tear down the frame and restore r0, r1, and lr. */ + { + BNEZ r0, .Lerror + ADDI_PTR r1, sp, 3 * REGSIZE + } + { + LD r1, r1 + ADDI_PTR r0, sp, 2 * REGSIZE + } + { + LD r0, r0 + ADDI_PTR sp, sp, 4 * REGSIZE + } + cfi_def_cfa_offset (0) + { + LD lr, sp + ADDLI_PTR r10, r0, UC_REG(54) + } + + /* Update the stored sp and lr. */ + { + ST r10, sp + ADDLI_PTR r10, r0, UC_REG(55) + } + ST r10, lr + + /* Tail-call setcontext to finish up. */ + { + move r0, r1 + j __setcontext + } + +.Lerror: + jrp lr +END (__swapcontext) + +weak_alias (__swapcontext, swapcontext) diff --git a/sysdeps/unix/sysv/linux/tile/sys/cachectl.h b/sysdeps/unix/sysv/linux/tile/sys/cachectl.h new file mode 100644 index 0000000000..72d9e21381 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/sys/cachectl.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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_CACHECTL_H +#define _SYS_CACHECTL_H 1 + +#include + +/* Get the kernel definition for the op bits. */ +#include + +__BEGIN_DECLS + +#ifdef __USE_MISC +extern int cacheflush (void *__addr, __const int __nbytes, __const int __op) __THROW; +#endif +extern int _flush_cache (char *__addr, __const int __nbytes, __const int __op) __THROW; + +__END_DECLS + +#endif /* sys/cachectl.h */ diff --git a/sysdeps/unix/sysv/linux/tile/sys/dataplane.h b/sysdeps/unix/sysv/linux/tile/sys/dataplane.h new file mode 100644 index 0000000000..d491affdb1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/sys/dataplane.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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_DATAPLANE_H +#define _SYS_DATAPLANE_H 1 + +/* Get the kernel definition for the flag bits. */ +#include + +__BEGIN_DECLS + +extern int set_dataplane (int flags); + +__END_DECLS + +#endif /* sys/dataplane.h */ diff --git a/sysdeps/unix/sysv/linux/tile/sys/procfs.h b/sysdeps/unix/sysv/linux/tile/sys/procfs.h new file mode 100644 index 0000000000..585a223dbb --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/sys/procfs.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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 +#include +#include + +#define __need_int_reg_t +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef __uint_reg_t elf_greg_t; + +/* And the whole bunch of them. We could have used `struct pt_regs' + from 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 64 +#define ELF_NFPREG 0 +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; +typedef elf_greg_t elf_fpregset_t[ELF_NFPREG]; + +/* 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 int pr_uid; + unsigned 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 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; + +/* Provide dummy declaration here; we don't have FP registers. */ +typedef int 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/sysdeps/unix/sysv/linux/tile/sys/ptrace.h b/sysdeps/unix/sysv/linux/tile/sys/ptrace.h new file mode 100644 index 0000000000..554171a377 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/sys/ptrace.h @@ -0,0 +1,145 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Get all general purpose registers used by a processes. */ + PTRACE_GETREGS = 12, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all general purpose registers used by a processes. */ + PTRACE_SETREGS = 13, +#define PT_SETREGS PTRACE_SETREGS + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24, +#define PT_SYSCALL PTRACE_SYSCALL + + /* Set ptrace filter options. */ + PTRACE_SETOPTIONS = 0x4200, +#define PT_SETOPTIONS PTRACE_SETOPTIONS + + /* Get last ptrace message. */ + PTRACE_GETEVENTMSG = 0x4201, +#define PT_GETEVENTMSG PTRACE_GETEVENTMSG + + /* Get siginfo for process. */ + PTRACE_GETSIGINFO = 0x4202, +#define PT_GETSIGINFO PTRACE_GETSIGINFO + + /* Set new siginfo for process. */ + PTRACE_SETSIGINFO = 0x4203 +#define PT_SETSIGINFO PTRACE_SETSIGINFO +}; + + +/* Options set using PTRACE_SETOPTIONS. */ +enum __ptrace_setoptions { + PTRACE_O_TRACESYSGOOD = 0x00000001, + PTRACE_O_TRACEFORK = 0x00000002, + PTRACE_O_TRACEVFORK = 0x00000004, + PTRACE_O_TRACECLONE = 0x00000008, + PTRACE_O_TRACEEXEC = 0x00000010, + PTRACE_O_TRACEVFORKDONE = 0x00000020, + PTRACE_O_TRACEEXIT = 0x00000040, + PTRACE_O_MASK = 0x0000007f +}; + +/* Wait extended result codes for the above trace options. */ +enum __ptrace_eventcodes { + PTRACE_EVENT_FORK = 1, + PTRACE_EVENT_VFORK = 2, + PTRACE_EVENT_CLONE = 3, + PTRACE_EVENT_EXEC = 4, + PTRACE_EVENT_VFORK_DONE = 5, + PTRACE_EVENT_EXIT = 6 +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/sysdeps/unix/sysv/linux/tile/sys/reg.h b/sysdeps/unix/sysv/linux/tile/sys/reg.h new file mode 100644 index 0000000000..1ab17ce82a --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/sys/reg.h @@ -0,0 +1,2 @@ +/* The traditional purpose of "sys/reg.h" is satisfied by "arch/abi.h". */ +#include diff --git a/sysdeps/unix/sysv/linux/tile/sys/ucontext.h b/sysdeps/unix/sysv/linux/tile/sys/ucontext.h new file mode 100644 index 0000000000..530802359b --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/sys/ucontext.h @@ -0,0 +1,71 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +/* Get register type and register names. */ +#include + +/* Type for general register. */ +typedef uint_reg_t greg_t; + +/* Number of general registers. Must agree with . */ +#define NGREG 64 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +#ifdef __USE_GNU +/* Names for interesting registers in the `gregset_t' array. */ +enum +{ + /* ... r0 through r51 are just 0 through 51 ... */ + REG_FP = TREG_FP, +# define REG_FP REG_FP + REG_TP = TREG_TP, +# define REG_TP REG_TP + REG_SP = TREG_SP, +# define REG_SP REG_SP + REG_LR = TREG_LR, +# define REG_LR REG_LR +}; +#endif + +/* A machine context is exactly a sigcontext. */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/sysdeps/unix/sysv/linux/tile/sys/user.h b/sysdeps/unix/sysv/linux/tile/sys/user.h new file mode 100644 index 0000000000..c871f1a03d --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/sys/user.h @@ -0,0 +1 @@ +/* This file is not needed, but in practice gdb might try to include it. */ diff --git a/sysdeps/unix/sysv/linux/tile/syscall.S b/sysdeps/unix/sysv/linux/tile/syscall.S new file mode 100644 index 0000000000..d802959185 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/syscall.S @@ -0,0 +1,33 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + .text +ENTRY (syscall) + FEEDBACK_ENTER(syscall) + { move TREG_SYSCALL_NR_NAME, r0; move r0, r1 } + { move r1, r2; move r2, r3 } + { move r3, r4; move r4, r5 } + { move r5, r6; move r6, r7 } + swint1 + BNEZ r1, 0f + jrp lr +PSEUDO_END (syscall) diff --git a/sysdeps/unix/sysv/linux/tile/sysdep.c b/sysdeps/unix/sysv/linux/tile/sysdep.c new file mode 100644 index 0000000000..f578e91888 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/sysdep.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int __syscall_error (int dummy, int err); +hidden_proto (__syscall_error) + +/* This routine is jumped to by all the syscall handlers, to stash + an error number into errno. */ +int +__syscall_error (int dummy, int err) +{ + __set_errno (err); + return -1; +} +hidden_def (__syscall_error) diff --git a/sysdeps/unix/sysv/linux/tile/sysdep.h b/sysdeps/unix/sysv/linux/tile/sysdep.h new file mode 100644 index 0000000000..cf6763de2c --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/sysdep.h @@ -0,0 +1,224 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#undef SYS_ify +#define SYS_ify(syscall_name) __NR_##syscall_name + + +#ifdef __ASSEMBLER__ + +/* The actual implementation of doing a syscall. */ +#define DO_CALL(syscall_name, args) \ + moveli TREG_SYSCALL_NR_NAME, SYS_ify(syscall_name); \ + swint1 + +/* TILE Linux returns the result in r0 (or a negative errno). + The kernel "owns" the code to decide if a given value is an error, + and puts errno in r1 if so, or otherwise zero. */ +#define PSEUDO(name, syscall_name, args) \ + ENTRY (name); \ + DO_CALL(syscall_name, args); \ + BNEZ r1, 0f + +#define ret jrp lr + +#ifndef PIC +/* For static code, on error jump to __syscall_error directly. */ +# define SYSCALL_ERROR_NAME __syscall_error +#elif !defined NOT_IN_libc || defined IS_IN_libpthread +/* Use the internal name for libc/libpthread shared objects. */ +# define SYSCALL_ERROR_NAME __GI___syscall_error +#else +/* Otherwise, on error do a full PLT jump. */ +# define SYSCALL_ERROR_NAME plt(__syscall_error) +#endif + +#define PSEUDO_END(name) \ +0: \ + j SYSCALL_ERROR_NAME; \ + END (name) + +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + ENTRY (name); \ + DO_CALL(syscall_name, args) + +#define ret_NOERRNO jrp lr + +#define PSEUDO_END_NOERRNO(name) \ + END (name) + +/* Convenience wrappers. */ +#define SYSCALL__(name, args) PSEUDO (__##name, name, args) +#define SYSCALL(name, args) PSEUDO (name, name, args) + +#else /* not __ASSEMBLER__ */ + +#include + +/* Define a macro which expands inline into the wrapper code for a system + call. */ +# undef INLINE_SYSCALL +# define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + INTERNAL_SYSCALL_DECL (err); \ + unsigned long val = INTERNAL_SYSCALL (name, err, nr, args); \ + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (val, err), 0)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (val, err)); \ + val = -1; \ + } \ + (long) val; }) + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + internal_syscall##nr (SYS_ify (name), err, args) + +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (number, err, args) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) int err + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) ({ (void) (val); (err) != 0; }) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err) ({ (void) (val); (err); }) + +#define internal_syscall0(num, err, dummy...) \ + ({ \ + long _sys_result, __SYSCALL_CLOBBER_DECLS; \ + __asm__ __volatile__ ( \ + "swint1" \ + : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ + : "R10" (num) \ + : __SYSCALL_CLOBBERS); \ + _sys_result; \ + }) + +#define internal_syscall1(num, err, arg0) \ + ({ \ + long _sys_result, __SYSCALL_CLOBBER_DECLS; \ + __asm__ __volatile__ ( \ + "swint1" \ + : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ + : "R10" (num), "R00" (arg0) \ + : __SYSCALL_CLOBBERS); \ + _sys_result; \ + }) + +#define internal_syscall2(num, err, arg0, arg1) \ + ({ \ + long _sys_result, __SYSCALL_CLOBBER_DECLS; \ + __asm__ __volatile__ ( \ + "swint1" \ + : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ + : "R10" (num), "R00" (arg0), "R01" (arg1) \ + : __SYSCALL_CLOBBERS); \ + _sys_result; \ + }) + +#define internal_syscall3(num, err, arg0, arg1, arg2) \ + ({ \ + long _sys_result, __SYSCALL_CLOBBER_DECLS; \ + __asm__ __volatile__ ( \ + "swint1" \ + : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ + : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2) \ + : __SYSCALL_CLOBBERS); \ + _sys_result; \ + }) + +#define internal_syscall4(num, err, arg0, arg1, arg2, arg3) \ + ({ \ + long _sys_result, __SYSCALL_CLOBBER_DECLS; \ + __asm__ __volatile__ ( \ + "swint1" \ + : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ + : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2), \ + "R03" (arg3) \ + : __SYSCALL_CLOBBERS); \ + _sys_result; \ + }) + +#define internal_syscall5(num, err, arg0, arg1, arg2, arg3, arg4) \ + ({ \ + long _sys_result, __SYSCALL_CLOBBER_DECLS; \ + __asm__ __volatile__ ( \ + "swint1" \ + : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ + : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2), \ + "R03" (arg3), "R04" (arg4) \ + : __SYSCALL_CLOBBERS); \ + _sys_result; \ + }) + +#define internal_syscall6(num, err, arg0, arg1, arg2, arg3, arg4, arg5) \ + ({ \ + long _sys_result, __SYSCALL_CLOBBER_DECLS; \ + __asm__ __volatile__ ( \ + "swint1" \ + : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \ + : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2), \ + "R03" (arg3), "R04" (arg4), "R05" (arg5) \ + : __SYSCALL_CLOBBERS); \ + _sys_result; \ + }) + +#undef __SYSCALL_CLOBBERS +#define __SYSCALL_CLOBBERS \ + "r6", "r7", \ + "r8", "r9", "r11", "r12", "r13", "r14", "r15", \ + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ + "r24", "r25", "r26", "r27", "r28", "r29", "memory" + +/* gcc doesn't seem to allow an input operand to be clobbered, so we + fake it with dummy outputs. */ +#define __SYSCALL_CLOBBER_DECLS \ + _clobber_r2, _clobber_r3, _clobber_r4, _clobber_r5, _clobber_r10 + +#define __SYSCALL_CLOBBER_OUTPUTS \ + "=R02" (_clobber_r2), "=R03" (_clobber_r3), "=R04" (_clobber_r4), \ + "=R05" (_clobber_r5), "=R10" (_clobber_r10) + +#endif /* not __ASSEMBLER__ */ + +/* Pointer mangling support. */ +#if defined NOT_IN_libc && defined IS_IN_rtld +/* We cannot use the thread descriptor because in ld.so we use setjmp + earlier than the descriptor is initialized. */ +#else +# ifdef __ASSEMBLER__ +# define PTR_MANGLE(reg, tmpreg) \ + ADDLI_PTR tmpreg, pt, POINTER_GUARD; \ + LD tmpreg, tmpreg; \ + xor reg, tmpreg, reg +# define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg) +# else +# define PTR_MANGLE(var) \ + (var) = (__typeof (var)) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ()) +# define PTR_DEMANGLE(var) PTR_MANGLE (var) +# endif +#endif diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/ioctl.S b/sysdeps/unix/sysv/linux/tile/tilegx/ioctl.S new file mode 100644 index 0000000000..9ccedd4c81 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/tilegx/ioctl.S @@ -0,0 +1,42 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + + +/* TILE-Gx specifies that "unsigned int" is sign extended in the high + 32 bits. But since the userspace API claims to be "unsigned long", + calls into __ioctl() will not be sign extended, but rather pass all + 64 bits of the argument. Therefore, when we pass the "request" + value to the kernel, we must explicitly sign-extend it to match the + kernel's internal use of "unsigned int" as the second argument, + which we do by casting to "unsigned int". */ + +#include + + .text +ENTRY (__ioctl) + FEEDBACK_ENTER(__ioctl) + { + addxi r1, r1, 0 + moveli TREG_SYSCALL_NR_NAME, __NR_ioctl + } + swint1 + BNEZ r1, 0f + jrp lr +PSEUDO_END (__ioctl) +weak_alias (__ioctl, ioctl) diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/ldconfig.h b/sysdeps/unix/sysv/linux/tile/tilegx/ldconfig.h new file mode 100644 index 0000000000..4610347a53 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/tilegx/ldconfig.h @@ -0,0 +1,27 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define SYSDEP_KNOWN_INTERPRETER_NAMES \ + { "/lib/ld.so.1", FLAG_ELF_LIBC6 }, \ + { "/lib32/ld.so.1", FLAG_ELF_LIBC6 }, +#define SYSDEP_KNOWN_LIBRARY_NAMES \ + { "libc.so.6", FLAG_ELF_LIBC6 }, \ + { "libm.so.6", FLAG_ELF_LIBC6 }, diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/register-dump.h b/sysdeps/unix/sysv/linux/tile/tilegx/register-dump.h new file mode 100644 index 0000000000..092c32b8fb --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/tilegx/register-dump.h @@ -0,0 +1,124 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* We will print the register dump in this format: + + R0: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R4: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R8: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R12: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R16: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R20: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R24: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R28: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R32: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R36: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R40: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R44: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R48: XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX + R52: XXXXXXXXXXXXXXXX TP: XXXXXXXXXXXXXXXX + SP: XXXXXXXXXXXXXXXX LR: XXXXXXXXXXXXXXXX + + PC: XXXXXXXXXXXXXXXX ICS: X FAULTNUM: XX + + */ + +static void +hexvalue (unsigned long int value, char *buf, size_t len) +{ + char *cp = _itoa_word (value, buf + len, 16, 0); + while (cp > buf) + *--cp = '0'; +} + +static void +register_dump (int fd, mcontext_t *ctx) +{ + char regs[59][16]; + struct iovec iov[132]; + size_t nr = 0; + unsigned int i; + +#define ADD_STRING(str) \ + iov[nr].iov_base = (char *) str; \ + iov[nr].iov_len = strlen (str); \ + ++nr +#define ADD_MEM(str, len) \ + iov[nr].iov_base = str; \ + iov[nr].iov_len = len; \ + ++nr + + /* Generate strings of register contents. */ + for (i = 0; i < 56; ++i) + hexvalue (ctx->gregs[i], regs[i], 16); + hexvalue (ctx->pc, regs[56], 16); + hexvalue (ctx->ics, regs[57], 1); + hexvalue (ctx->faultnum, regs[58], 2); + + /* Generate the output. */ + for (i = 0; i < 56;) + { + const char *prefixes[] = { + "Register dump:\n\n R0: ", + "\n R4: ", + "\n R8: ", + "\n R12: ", + "\n R16: ", + "\n R20: ", + "\n R24: ", + "\n R28: ", + "\n R32: ", + "\n R36: ", + "\n R40: ", + "\n R44: ", + "\n R48: " + }; + ADD_STRING (prefixes[i / 4]); + do + { + ADD_MEM (regs[i], 16); + ADD_STRING (" "); + } + while (++i % 4); + } + ADD_STRING ("\n R52: "); + ADD_MEM (regs[52], 16); + ADD_STRING (" TP: "); + ADD_MEM (regs[53], 16); + ADD_STRING ("\n SP: "); + ADD_MEM (regs[54], 16); + ADD_STRING (" LR: "); + ADD_MEM (regs[55], 16); + ADD_STRING ("\n\n PC: "); + ADD_MEM (regs[56], 16); + ADD_STRING (" ICS: "); + ADD_MEM (regs[57], 1); + ADD_STRING (" FAULTNUM: "); + ADD_MEM (regs[58], 2); + ADD_STRING ("\n"); + + /* Write the stuff out. */ + writev (fd, iov, nr); +} + + +#define REGISTER_DUMP register_dump (fd, &ctx->uc_mcontext) diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/Implies b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/Implies new file mode 100644 index 0000000000..9090d3fb8b --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/Implies @@ -0,0 +1,4 @@ +unix/sysv/linux/tile/tilegx +unix/sysv/linux/tile +unix/sysv/linux/generic/wordsize-32 +unix/sysv/linux/generic diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/Implies b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/Implies new file mode 100644 index 0000000000..e4e0800c0a --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/Implies @@ -0,0 +1,4 @@ +unix/sysv/linux/tile/tilegx +unix/sysv/linux/tile +unix/sysv/linux/generic +unix/sysv/linux/wordsize-64 diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/Implies b/sysdeps/unix/sysv/linux/tile/tilepro/Implies new file mode 100644 index 0000000000..0023bb77aa --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/tilepro/Implies @@ -0,0 +1,3 @@ +unix/sysv/linux/tile +unix/sysv/linux/generic/wordsize-32 +unix/sysv/linux/generic diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/ldconfig.h b/sysdeps/unix/sysv/linux/tile/tilepro/ldconfig.h new file mode 100644 index 0000000000..5a10db2575 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/tilepro/ldconfig.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define SYSDEP_KNOWN_INTERPRETER_NAMES \ + { "/lib/ld.so.1", FLAG_ELF_LIBC6 }, +#define SYSDEP_KNOWN_LIBRARY_NAMES \ + { "libc.so.6", FLAG_ELF_LIBC6 }, \ + { "libm.so.6", FLAG_ELF_LIBC6 }, diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/register-dump.h b/sysdeps/unix/sysv/linux/tile/tilepro/register-dump.h new file mode 100644 index 0000000000..f559d15032 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/tilepro/register-dump.h @@ -0,0 +1,112 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + Based on work contributed by Ulrich Drepper , 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. */ + +#include +#include + +/* We will print the register dump in this format: + + R0: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX + R8: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX + R16: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX + R24: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX + R32: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX + R40: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX + R48: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX + R52: XXXXXXXX TP: XXXXXXXX SP: XXXXXXXX LR: XXXXXXXX + + PC: XXXXXXXX ICS: X FAULTNUM: XX + + */ + +static void +hexvalue (unsigned long int value, char *buf, size_t len) +{ + char *cp = _itoa_word (value, buf + len, 16, 0); + while (cp > buf) + *--cp = '0'; +} + +static void +register_dump (int fd, mcontext_t *ctx) +{ + char regs[59][8]; + struct iovec iov[143]; + size_t nr = 0; + unsigned int i; + +#define ADD_STRING(str) \ + iov[nr].iov_base = (char *) str; \ + iov[nr].iov_len = strlen (str); \ + ++nr +#define ADD_MEM(str, len) \ + iov[nr].iov_base = str; \ + iov[nr].iov_len = len; \ + ++nr + + /* Generate strings of register contents. */ + for (i = 0; i < 56; ++i) + hexvalue (ctx->gregs[i], regs[i], 8); + hexvalue (ctx->pc, regs[56], 8); + hexvalue (ctx->ics, regs[57], 1); + hexvalue (ctx->faultnum, regs[58], 2); + + /* Generate the output. */ + for (i = 0; i < 52;) + { + const char *prefixes[] = { + "Register dump:\n\n R0: ", + "\n R8: ", + "\n R16: ", + "\n R24: ", + "\n R32: ", + "\n R40: ", + "\n R48: " + }; + ADD_STRING (prefixes[i / 8]); + do + { + ADD_MEM (regs[i], 8); + ADD_STRING (" "); + } + while (++i % 8 && i < 52); + } + ADD_STRING ("\n R52: "); + ADD_MEM (regs[52], 8); + ADD_STRING (" TP: "); + ADD_MEM (regs[53], 8); + ADD_STRING (" SP: "); + ADD_MEM (regs[54], 8); + ADD_STRING (" LR: "); + ADD_MEM (regs[55], 8); + ADD_STRING ("\n\n PC: "); + ADD_MEM (regs[56], 8); + ADD_STRING (" ICS: "); + ADD_MEM (regs[57], 1); + ADD_STRING (" FAULTNUM: "); + ADD_MEM (regs[58], 2); + ADD_STRING ("\n"); + + /* Write the stuff out. */ + writev (fd, iov, nr); +} + + +#define REGISTER_DUMP register_dump (fd, &ctx->uc_mcontext) diff --git a/sysdeps/unix/sysv/linux/tile/ucontext_i.h b/sysdeps/unix/sysv/linux/tile/ucontext_i.h new file mode 100644 index 0000000000..f255572ead --- /dev/null +++ b/sysdeps/unix/sysv/linux/tile/ucontext_i.h @@ -0,0 +1,42 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + 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. */ + +/* Definitions of offsets within the ucontext_t structure. Note + that for convenience we use __SIZEOF_POINTER__ for "long" and + "ssize_t" fields (and their unsigned counterparts) as well. */ + +#define UC_FLAGS_OFFSET 0 +#define UC_LINK_OFFSET (UC_FLAGS_OFFSET + __SIZEOF_POINTER__) +#define UC_STACK_SP_OFFSET (UC_LINK_OFFSET + __SIZEOF_POINTER__) +#define UC_STACK_FLAGS_OFFSET (UC_STACK_SP_OFFSET + __SIZEOF_POINTER__) +#define UC_STACK_SIZE_OFFSET (UC_STACK_FLAGS_OFFSET + __SIZEOF_POINTER__) +#define UC_STACK_MCONTEXT_OFFSET (UC_STACK_SIZE_OFFSET + __SIZEOF_POINTER__) +#define UC_REG(i) (UC_STACK_MCONTEXT_OFFSET + ((i) * REGSIZE)) +#define UC_NREGS 64 +#define UC_SIGMASK_OFFSET UC_REG(UC_NREGS) +#define UC_SIZE (UC_SIGMASK_OFFSET + (_NSIG / 8)) + +/* From */ +#define SI_MAX_SIZE 128 + +/* From */ +#define _NSIG 64 +#define SIG_BLOCK 0 /* for blocking signals */ +#define SIG_UNBLOCK 1 /* for unblocking signals */ +#define SIG_SETMASK 2 /* for setting the signal mask */