summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@uclibc-ng.org>2017-12-16 21:01:39 +0100
committerWaldemar Brodkorb <wbx@uclibc-ng.org>2017-12-31 11:12:07 +0100
commit23bb649090ff588e8642f0c581cfe7ce2d29c757 (patch)
tree4a68d696415fce9f2dd50edf27a79bacbde3fc50
parent604781391549faafc59516700d9439ab1a7ec19b (diff)
m68k: add NPTL/TLS support
Port over NPTL/TLS support from GNU C Library. In the first step only the slower syscall is used for TLS access. The uClibc-ng testsuite shows 79 errors, so their is room for bugfixes and improvements.
-rw-r--r--extra/Configs/Config.in1
-rw-r--r--include/elf.h23
-rw-r--r--ldso/ldso/m68k/dl-sysdep.h12
-rw-r--r--ldso/ldso/m68k/elfinterp.c45
-rw-r--r--ldso/ldso/m68k/m68k_read_tp.S48
-rw-r--r--libc/sysdeps/linux/common/libgcc_s.h4
-rw-r--r--libc/sysdeps/linux/m68k/Makefile.arch3
-rw-r--r--libc/sysdeps/linux/m68k/clone.S108
-rw-r--r--libc/sysdeps/linux/m68k/jmpbuf-unwind.h39
-rw-r--r--libc/sysdeps/linux/m68k/m68k_read_tp.S1
-rw-r--r--libc/sysdeps/linux/m68k/sys/reg.h101
-rw-r--r--libc/sysdeps/linux/m68k/sysdep.h26
-rw-r--r--libc/sysdeps/linux/m68k/vfork.S30
-rw-r--r--libpthread/nptl/sysdeps/m68k/Makefile6
-rw-r--r--libpthread/nptl/sysdeps/m68k/Makefile.arch1
-rw-r--r--libpthread/nptl/sysdeps/m68k/dl-tls.h46
-rw-r--r--libpthread/nptl/sysdeps/m68k/libc-tls.c32
-rw-r--r--libpthread/nptl/sysdeps/m68k/pthread_spin_lock.c65
-rw-r--r--libpthread/nptl/sysdeps/m68k/pthread_spin_trylock.c26
-rw-r--r--libpthread/nptl/sysdeps/m68k/pthreaddef.h36
-rw-r--r--libpthread/nptl/sysdeps/m68k/tcb-offsets.sym10
-rw-r--r--libpthread/nptl/sysdeps/m68k/tls.h178
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/m68k/Makefile6
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/m68k/Makefile.arch4
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/m68k/bits/pthreadtypes.h179
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/m68k/bits/semaphore.h34
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/m68k/createthread.c6
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/m68k/fork.c29
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/m68k/lowlevellock.h281
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/m68k/pthread_once.c100
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h33
31 files changed, 1442 insertions, 71 deletions
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index b5ee294db..181d459fb 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -544,7 +544,6 @@ config UCLIBC_HAS_THREADS_NATIVE
!TARGET_h8300 && \
!TARGET_hppa && \
!TARGET_ia64 && \
- !TARGET_m68k && \
ARCH_USE_MMU
help
If you want to compile uClibc with NPTL support, then answer Y.
diff --git a/include/elf.h b/include/elf.h
index fcb546a0f..6b0a8757e 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -1292,8 +1292,29 @@ typedef struct
#define R_68K_GLOB_DAT 20 /* Create GOT entry */
#define R_68K_JMP_SLOT 21 /* Create PLT entry */
#define R_68K_RELATIVE 22 /* Adjust by program base */
+#define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */
+#define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */
+#define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */
+#define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */
+#define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */
+#define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */
+#define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */
+#define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */
+#define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */
+#define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */
+#define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */
+#define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */
+#define R_68K_TLS_LE32 37 /* 32 bit offset relative to
+ static TLS block */
+#define R_68K_TLS_LE16 38 /* 16 bit offset relative to
+ static TLS block */
+#define R_68K_TLS_LE8 39 /* 8 bit offset relative to
+ static TLS block */
+#define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */
+#define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */
+#define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */
/* Keep this the last entry. */
-#define R_68K_NUM 23
+#define R_68K_NUM 43
/* Intel 80386 specific definitions. */
diff --git a/ldso/ldso/m68k/dl-sysdep.h b/ldso/ldso/m68k/dl-sysdep.h
index 8ac892655..21937b259 100644
--- a/ldso/ldso/m68k/dl-sysdep.h
+++ b/ldso/ldso/m68k/dl-sysdep.h
@@ -27,12 +27,16 @@ do { \
struct elf_resolve;
extern unsigned long _dl_linux_resolver (struct elf_resolve *, int);
-/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
- PLT entries should not be allowed to define the value.
- ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+/* 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_COPY 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_68K_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+ ((((type) == R_68K_JMP_SLOT \
+ || (type) == R_68K_TLS_DTPMOD32 \
+ || (type) == R_68K_TLS_DTPREL32 \
+ || (type) == R_68K_TLS_TPREL32) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_68K_COPY) * ELF_RTYPE_CLASS_COPY))
/* Return the link-time address of _DYNAMIC. Conveniently, this is the
diff --git a/ldso/ldso/m68k/elfinterp.c b/ldso/ldso/m68k/elfinterp.c
index 15a2c43b1..25ea23067 100644
--- a/ldso/ldso/m68k/elfinterp.c
+++ b/ldso/ldso/m68k/elfinterp.c
@@ -150,6 +150,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
#if defined (__SUPPORT_LD_DEBUG__)
ElfW(Addr) old_val;
#endif
+#if defined USE_TLS && USE_TLS
+ struct elf_resolve *tls_tpnt = NULL;
+#endif
reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
reloc_type = ELF_R_TYPE(rpnt->r_info);
@@ -167,16 +170,28 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
* might have been intentional. We should not be linking local
* symbols here, so all bases should be covered.
*/
- if (unlikely(!symbol_addr && ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK)) {
- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
- _dl_exit(1);
+ if (unlikely (!symbol_addr &&
+ ELF_ST_TYPE (sym_ref.sym->st_info) != STT_TLS &&
+ ELF_ST_BIND (sym_ref.sym->st_info) != STB_WEAK)) {
+ return 1;
}
if (_dl_trace_prelink) {
_dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
&sym_ref, elf_machine_type_class(reloc_type));
}
+#if defined USE_TLS && USE_TLS
+ tls_tpnt = sym_ref.tpnt;
+#endif
}
+#if defined USE_TLS && USE_TLS
+ /* In case of a TLS reloc, tls_tpnt NULL means we have an 'anonymous'
+ symbol. This is the case for a static tls variable, so the lookup
+ module is just that one is referencing the tls variable. */
+ if (!tls_tpnt)
+ tls_tpnt = tpnt;
+#endif
+
#if defined (__SUPPORT_LD_DEBUG__)
old_val = *reloc_addr;
#endif
@@ -209,13 +224,6 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
case R_68K_JMP_SLOT:
*reloc_addr = symbol_addr + rpnt->r_addend;
break;
- /* handled by elf_machine_relative()
- case R_68K_RELATIVE:
- *reloc_addr = ((unsigned int) tpnt->loadaddr
- / * Compatibility kludge. * /
- + (rpnt->r_addend ? : *reloc_addr));
- */
- break;
case R_68K_COPY:
if (symbol_addr) {
#if defined (__SUPPORT_LD_DEBUG__)
@@ -234,7 +242,22 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
_dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
#endif
break;
-
+#if defined USE_TLS && USE_TLS
+ case R_68K_TLS_DTPMOD32:
+ *reloc_addr = tls_tpnt->l_tls_modid;
+ break;
+ case R_68K_TLS_DTPREL32:
+ if (sym_ref.sym != NULL)
+ *reloc_addr = TLS_DTPREL_VALUE (sym_ref.sym, rpnt);
+ break;
+ case R_68K_TLS_TPREL32:
+ if (sym_ref.sym != NULL)
+ {
+ CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
+ *reloc_addr = TLS_TPREL_VALUE ((struct link_map *) tls_tpnt, sym_ref.sym, rpnt);
+ }
+ break;
+#endif
default:
return -1; /* Calls _dl_exit(1). */
}
diff --git a/ldso/ldso/m68k/m68k_read_tp.S b/ldso/ldso/m68k/m68k_read_tp.S
new file mode 100644
index 000000000..cb5280e67
--- /dev/null
+++ b/ldso/ldso/m68k/m68k_read_tp.S
@@ -0,0 +1,48 @@
+/* Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+ .text
+# ifdef IS_IN_rtld
+/* rtld gets a hidden copy of __m68k_read_tp. */
+ .hidden __m68k_read_tp
+# endif
+
+ENTRY (__m68k_read_tp)
+ move.l #__NR_get_thread_area, %d0
+ trap #0
+ move.l %d0, %a0
+ rts
+END (__m68k_read_tp)
diff --git a/libc/sysdeps/linux/common/libgcc_s.h b/libc/sysdeps/linux/common/libgcc_s.h
index e74a1034c..bf43d78a7 100644
--- a/libc/sysdeps/linux/common/libgcc_s.h
+++ b/libc/sysdeps/linux/common/libgcc_s.h
@@ -1,2 +1,6 @@
/* Name of libgcc_s library provided by gcc. */
+#if defined(__m68k__)
+#define LIBGCC_S_SO "libgcc_s.so.2"
+#else
#define LIBGCC_S_SO "libgcc_s.so.1"
+#endif
diff --git a/libc/sysdeps/linux/m68k/Makefile.arch b/libc/sysdeps/linux/m68k/Makefile.arch
index 88caa116f..191791aef 100644
--- a/libc/sysdeps/linux/m68k/Makefile.arch
+++ b/libc/sysdeps/linux/m68k/Makefile.arch
@@ -7,4 +7,5 @@
CSRC-y := brk.c __syscall_error.c
-SSRC-y := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S vfork.S
+SSRC-y := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S vfork.S \
+ m68k_read_tp.S
diff --git a/libc/sysdeps/linux/m68k/clone.S b/libc/sysdeps/linux/m68k/clone.S
index 7eddff10c..24071235b 100644
--- a/libc/sysdeps/linux/m68k/clone.S
+++ b/libc/sysdeps/linux/m68k/clone.S
@@ -1,54 +1,94 @@
-/* Adapted from glibc */
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. */
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ Contributed by Andreas Schwab (schwab@issan.informatik.uni-dortmund.de)
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
/* clone is even more special than fork as it mucks with stacks
and invokes a function in the right context after its all over. */
#define _ERRNO_H
+#include <sysdep.h>
#include <features.h>
#include <bits/errno.h>
#include <sys/syscall.h>
#include "m68k_pic.S"
-/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+ void *parent_tidptr, void *tls, void *child_tidptr) */
-.text
-.align 4
-.type clone,@function
-.globl clone;
-clone:
+ .text
+ .align 4
+ .globl __clone
+ .type __clone,@function
+
+__clone:
/* Sanity check arguments. */
- movel #-EINVAL, %d0
- movel 4(%sp), %d1 /* no NULL function pointers */
- movel %d1, %a0
- tstl %d1
+ movel #-EINVAL, %d0
+ movel 4(%sp), %a0 /* no NULL function pointers */
+ tstl %a0
beq.w __syscall_error_trampoline
- movel 8(%sp), %d1 /* no NULL stack pointers */
- movel %d1, %a1
- tstl %d1
+ movel 8(%sp), %a1 /* no NULL stack pointers */
+ tstl %a1
beq.w __syscall_error_trampoline
/* Allocate space and copy the argument onto the new stack. */
movel 16(%sp), -(%a1)
/* Do the system call */
-#if 1 /* defined (CONFIG_COLDFIRE) */
- movel %d2, %d1 /* save %d2 and get stack pointer */
- movel %a1, %d2
- movel %d1, %a1
+ movel 12(%sp), %d1 /* get flags */
+ movel %d3, -(%a1) /* save %d3 and get parent_tidptr */
+ movel %d3, -(%sp)
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (%d3, 0)
+ movel 20+4(%sp), %d3
+ movel %d4, -(%a1) /* save %d4 and get child_tidptr */
+ movel %d4, -(%sp)
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (%d4, 0)
+ movel 28+8(%sp), %d4
+ movel %d5, -(%a1) /* save %d5 and get tls */
+ movel %d5, -(%sp)
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (%d5, 0)
+ movel 24+12(%sp), %d5
+ /* save %d2 and get stack pointer */
+#ifdef __mcoldfire__
+ movel %d2, -(%a1)
+ movel %d2, -(%sp)
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (%d2, 0)
+ movel %a1, %d2
#else
- exg %d2, %a1 /* save %d2 and get stack pointer */
+ exg %d2, %a1 /* save %d2 and get stack pointer */
+ cfi_register (%d2, %a1)
#endif
- movel 12(%sp), %d1 /* get flags */
movel #__NR_clone, %d0
+
+ /* End FDE now, because in the child the unwind info will be
+ wrong. */
+ cfi_endproc
+
trap #0
-#if 1 /* defined (CONFIG_COLDFIRE) */
- movel %d2, %d1 /* restore %d2 */
- movel %a1, %d2
- movel %d1, %a1
+#ifdef __mcoldfire__
+ movel (%sp)+, %d2
#else
- exg %d2, %a1 /* restore %d2 */
+ exg %d2, %a1 /* restore %d2 */
#endif
+ movel (%sp)+, %d5 /* restore %d5, %d4 and %d3 */
+ movel (%sp)+, %d4
+ movel (%sp)+, %d3
tstl %d0
bmi.w __syscall_error_trampoline
@@ -57,13 +97,21 @@ clone:
rts
thread_start:
- /*subl %fp, %fp*/ /* terminate the stack frame */
- jsr (%a0)
- movel %d0, -(%sp)
+ cfi_startproc
+ cfi_undefined (pc) /* Mark end of stack */
+ subl %fp, %fp /* terminate the stack frame */
+ jsr (%a0)
+ movel %d0, %d1
movel #__NR_exit, %d0
trap #0
- /*jsr exit*/
+ cfi_endproc
+
+ cfi_startproc
__syscall_error_trampoline:
JUMP __syscall_error,%a0
+.size __clone,.-__clone
+
+weak_alias(__clone,clone)
+libc_hidden_def(clone)
diff --git a/libc/sysdeps/linux/m68k/jmpbuf-unwind.h b/libc/sysdeps/linux/m68k/jmpbuf-unwind.h
index c5a8886e2..8744ec7e8 100644
--- a/libc/sysdeps/linux/m68k/jmpbuf-unwind.h
+++ b/libc/sysdeps/linux/m68k/jmpbuf-unwind.h
@@ -1,8 +1,19 @@
-/*
- * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
+/* Examine __jmp_buf for unwinding frames. m68k version.
+ Copyright (C) 2006-2017 Free Software Foundation, Inc.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
#include <setjmp.h>
@@ -10,3 +21,21 @@
containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address) \
((void *) (address) < (void *) (jmpbuf)->__aregs[5])
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <stdint.h>
+#include <unwind.h>
+
+#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 = (uintptr_t) regs[0].__sp;
+ return sp;
+}
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+ ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+#endif
diff --git a/libc/sysdeps/linux/m68k/m68k_read_tp.S b/libc/sysdeps/linux/m68k/m68k_read_tp.S
new file mode 100644
index 000000000..523e1b38a
--- /dev/null
+++ b/libc/sysdeps/linux/m68k/m68k_read_tp.S
@@ -0,0 +1 @@
+#include <ldso/ldso/m68k/m68k_read_tp.S>
diff --git a/libc/sysdeps/linux/m68k/sys/reg.h b/libc/sysdeps/linux/m68k/sys/reg.h
new file mode 100644
index 000000000..133c862b4
--- /dev/null
+++ b/libc/sysdeps/linux/m68k/sys/reg.h
@@ -0,0 +1,101 @@
+/* Copyright (C) 1998-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_REG_H
+#define _SYS_REG_H 1
+
+/* Index into an array of 4 byte integers returned from ptrace for
+ location of the users' stored general purpose registers. */
+
+enum
+{
+ PT_D1 = 0,
+#define PT_D1 PT_D1
+ PT_D2 = 1,
+#define PT_D2 PT_D2
+ PT_D3 = 2,
+#define PT_D3 PT_D3
+ PT_D4 = 3,
+#define PT_D4 PT_D4
+ PT_D5 = 4,
+#define PT_D5 PT_D5
+ PT_D6 = 5,
+#define PT_D6 PT_D6
+ PT_D7 = 6,
+#define PT_D7 PT_D7
+ PT_A0 = 7,
+#define PT_A0 PT_A0
+ PT_A1 = 8,
+#define PT_A1 PT_A1
+ PT_A2 = 9,
+#define PT_A2 PT_A2
+ PT_A3 = 10,
+#define PT_A3 PT_A3
+ PT_A4 = 11,
+#define PT_A4 PT_A4
+ PT_A5 = 12,
+#define PT_A5 PT_A5
+ PT_A6 = 13,
+#define PT_A6 PT_A6
+ PT_D0 = 14,
+#define PT_D0 PT_D0
+ PT_USP = 15,
+#define PT_USP PT_USP
+ PT_ORIG_D0 = 16,
+#define PT_ORIG_D0 PT_ORIG_D0
+ PT_SR = 17,
+#define PT_SR PT_SR
+ PT_PC = 18,
+#define PT_PC PT_PC
+
+#ifdef __mcoldfire__
+ PT_FP0 = 21,
+ PT_FP1 = 23,
+ PT_FP2 = 25,
+ PT_FP3 = 27,
+ PT_FP4 = 29,
+ PT_FP5 = 31,
+ PT_FP6 = 33,
+ PT_FP7 = 35,
+#else
+ PT_FP0 = 21,
+ PT_FP1 = 24,
+ PT_FP2 = 27,
+ PT_FP3 = 30,
+ PT_FP4 = 33,
+ PT_FP5 = 36,
+ PT_FP6 = 39,
+ PT_FP7 = 42,
+#endif
+#define PT_FP0 PT_FP0
+#define PT_FP1 PT_FP1
+#define PT_FP2 PT_FP2
+#define PT_FP3 PT_FP3
+#define PT_FP4 PT_FP4
+#define PT_FP5 PT_FP5
+#define PT_FP6 PT_FP6
+#define PT_FP7 PT_FP7
+
+ PT_FPCR = 45,
+#define PT_FPCR PT_FPCR
+ PT_FPSR = 46,
+#define PT_FPSR PT_FPSR
+ PT_FPIAR = 47
+#define PT_FPIAR PT_FPIAR
+};
+
+#endif /* _SYS_REG_H */
diff --git a/libc/sysdeps/linux/m68k/sysdep.h b/libc/sysdeps/linux/m68k/sysdep.h
new file mode 100644
index 000000000..9c18aae97
--- /dev/null
+++ b/libc/sysdeps/linux/m68k/sysdep.h
@@ -0,0 +1,26 @@
+#include <common/sysdep.h>
+
+#ifdef __ASSEMBLER__
+
+/* Define an entry point visible from C.
+
+ There is currently a bug in gdb which prevents us from specifying
+ incomplete stabs information. Fake some entries here which specify
+ the current source file. */
+# define ENTRY(name) \
+ .globl C_SYMBOL_NAME(name); \
+ .type C_SYMBOL_NAME(name),@function; \
+ .p2align 2; \
+ C_LABEL(name) \
+ cfi_startproc; \
+
+# undef END
+# define END(name) \
+ cfi_endproc; \
+ .size name,.-name
+
+/* Load the address of the GOT into register R. */
+# define LOAD_GOT(R) \
+ lea _GLOBAL_OFFSET_TABLE_@GOTPC (%pc), R
+
+#endif
diff --git a/libc/sysdeps/linux/m68k/vfork.S b/libc/sysdeps/linux/m68k/vfork.S
index bde9d5a3a..eb1639e37 100644
--- a/libc/sysdeps/linux/m68k/vfork.S
+++ b/libc/sysdeps/linux/m68k/vfork.S
@@ -10,8 +10,6 @@
#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */
#endif
-#define IMM #
-
.text
.align 2
.globl __vfork
@@ -19,26 +17,22 @@
.type __vfork,@function
__vfork:
- movl %sp@+, %a1 /* save the return address for later */
- movl IMM __NR_vfork,%d0
+ /* Pop the return PC value into A0. */
+ movel %sp@+, %a0
+
+ /* Stuff the syscall number in D0 and trap into the kernel. */
+ movel #SYS_ify (vfork), %d0
trap #0
- movl %a1, -(%sp)
- cmpil #-4096,%d0
- blss 1f
+ tstl %d0
+ jmi .Lerror /* Branch forward if it failed. */
- neg.l %d0
-#ifndef __PIC__ /* needs handling as the other archs */
- movl errno, %a0
-#else
- movl errno@GOT(%a5), %a0
-#endif
- movl %d0, %a0@
- move.l #-1, %d0
+ /* Jump to the return PC. */
+ jmp %a0@
-1:
- move.l %d0, %a0
- rts
+.Lerror:
+ /* Push back the return PC. */
+ movel %a0,%sp@-
.size __vfork,.-__vfork
weak_alias(__vfork,vfork)
diff --git a/libpthread/nptl/sysdeps/m68k/Makefile b/libpthread/nptl/sysdeps/m68k/Makefile
new file mode 100644
index 000000000..43dc60a42
--- /dev/null
+++ b/libpthread/nptl/sysdeps/m68k/Makefile
@@ -0,0 +1,6 @@
+top_srcdir=../../../../
+top_builddir=../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules
diff --git a/libpthread/nptl/sysdeps/m68k/Makefile.arch b/libpthread/nptl/sysdeps/m68k/Makefile.arch
new file mode 100644
index 000000000..7f6e1cd5b
--- /dev/null
+++ b/libpthread/nptl/sysdeps/m68k/Makefile.arch
@@ -0,0 +1 @@
+libc_arch_a_CSRC = libc-tls.c
diff --git a/libpthread/nptl/sysdeps/m68k/dl-tls.h b/libpthread/nptl/sysdeps/m68k/dl-tls.h
new file mode 100644
index 000000000..c0af06e1e
--- /dev/null
+++ b/libpthread/nptl/sysdeps/m68k/dl-tls.h
@@ -0,0 +1,46 @@
+/* Thread-local storage handling in the ELF dynamic linker. M68K version.
+ Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+
+/* 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;
+
+/* The thread pointer points 0x7000 past the first static TLS block. */
+#define TLS_TP_OFFSET 0x7000
+
+/* Dynamic thread vector pointers point 0x8000 past the start of each
+ TLS block. */
+#define TLS_DTV_OFFSET 0x8000
+
+/* Compute the value for a TPREL reloc. */
+#define TLS_TPREL_VALUE(sym_map, sym, reloc) \
+ ((sym_map)->l_tls_offset + (sym)->st_value + (reloc)->r_addend \
+ - TLS_TP_OFFSET)
+
+/* Compute the value for a DTPREL reloc. */
+#define TLS_DTPREL_VALUE(sym, reloc) \
+ ((sym)->st_value + (reloc)->r_addend - TLS_DTV_OFFSET)
+
+extern void *__tls_get_addr (tls_index *ti);
+
+#define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET)
+#define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET)
diff --git a/libpthread/nptl/sysdeps/m68k/libc-tls.c b/libpthread/nptl/sysdeps/m68k/libc-tls.c
new file mode 100644
index 000000000..50fc030af
--- /dev/null
+++ b/libpthread/nptl/sysdeps/m68k/libc-tls.c
@@ -0,0 +1,32 @@
+/* Thread-local storage handling in the ELF dynamic linker. m68k version.
+ Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdeps/generic/libc-tls.c>
+#include <dl-tls.h>
+
+/* On M68K, linker optimizations are not required, so __tls_get_addr
+ can be called even in statically linked binaries. In this case module
+ must be always 1 and PT_TLS segment exist in the binary, otherwise it
+ would not link. */
+
+void *
+__tls_get_addr (tls_index *ti)
+{
+ dtv_t *dtv = THREAD_DTV ();
+ return (char *) dtv[1].pointer.val + GET_ADDR_OFFSET;
+}
diff --git a/libpthread/nptl/sysdeps/m68k/pthread_spin_lock.c b/libpthread/nptl/sysdeps/m68k/pthread_spin_lock.c
new file mode 100644
index 000000000..cec3acbc6
--- /dev/null
+++ b/libpthread/nptl/sysdeps/m68k/pthread_spin_lock.c
@@ -0,0 +1,65 @@
+/* pthread_spin_lock -- lock a spin lock. Generic version.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+ 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