summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurelien Jacquiot <a-jacquiot@ti.com>2011-02-23 13:04:59 +0100
committerBernd Schmidt <bernds@codesourcery.com>2011-03-05 18:10:15 +0100
commit46d6a24872b7fa2717f8f71b5e0598a14d38e1f6 (patch)
tree886cf5a54ef7fd260acf2dd7d1722acea1c62186
parent817f685f4c65ed1af6eef79749b1f158eedd5bfc (diff)
The C6X port
This adds support for the TI C6X family of processors. Signed-off-by: Mark Salter <msalter@redhat.com> Signed-off-by: Aurelien Jacquiot <a-jacquiot@ti.com> Signed-off-by: Bernd Schmidt <bernds@codesourcery.com>
-rw-r--r--Rules.mak12
-rw-r--r--extra/Configs/Config.c6x34
-rw-r--r--extra/Configs/Config.in7
-rw-r--r--extra/Configs/Config.in.arch4
-rw-r--r--include/elf.h45
-rw-r--r--ldso/ldso/c6x/dl-debug.h49
-rw-r--r--ldso/ldso/c6x/dl-inlines.h91
-rw-r--r--ldso/ldso/c6x/dl-startup.h122
-rw-r--r--ldso/ldso/c6x/dl-syscalls.h25
-rw-r--r--ldso/ldso/c6x/dl-sysdep.h209
-rw-r--r--ldso/ldso/c6x/elfinterp.c296
-rw-r--r--ldso/ldso/c6x/resolve.S68
-rw-r--r--libc/sysdeps/linux/c6x/Makefile13
-rw-r--r--libc/sysdeps/linux/c6x/Makefile.arch15
-rw-r--r--libc/sysdeps/linux/c6x/__longjmp.S47
-rw-r--r--libc/sysdeps/linux/c6x/_vfork.S55
-rw-r--r--libc/sysdeps/linux/c6x/bits/byteswap.h35
-rw-r--r--libc/sysdeps/linux/c6x/bits/elf-dsbt.h123
-rw-r--r--libc/sysdeps/linux/c6x/bits/endian.h11
-rw-r--r--libc/sysdeps/linux/c6x/bits/fcntl.h235
-rw-r--r--libc/sysdeps/linux/c6x/bits/kernel_stat.h52
-rw-r--r--libc/sysdeps/linux/c6x/bits/kernel_types.h46
-rw-r--r--libc/sysdeps/linux/c6x/bits/mathdef.h39
-rw-r--r--libc/sysdeps/linux/c6x/bits/nan.h57
-rw-r--r--libc/sysdeps/linux/c6x/bits/poll.h43
-rw-r--r--libc/sysdeps/linux/c6x/bits/resource.h209
-rw-r--r--libc/sysdeps/linux/c6x/bits/setjmp.h39
-rw-r--r--libc/sysdeps/linux/c6x/bits/sigcontextinfo.h26
-rw-r--r--libc/sysdeps/linux/c6x/bits/stackinfo.h28
-rw-r--r--libc/sysdeps/linux/c6x/bits/stat.h174
-rw-r--r--libc/sysdeps/linux/c6x/bits/syscalls.h182
-rw-r--r--libc/sysdeps/linux/c6x/bits/uClibc_arch_features.h48
-rw-r--r--libc/sysdeps/linux/c6x/bits/wordsize.h19
-rw-r--r--libc/sysdeps/linux/c6x/brk.c54
-rw-r--r--libc/sysdeps/linux/c6x/bsd-_setjmp.s48
-rw-r--r--libc/sysdeps/linux/c6x/bsd-setjmp.S67
-rw-r--r--libc/sysdeps/linux/c6x/clone.S97
-rw-r--r--libc/sysdeps/linux/c6x/crt1.S67
-rw-r--r--libc/sysdeps/linux/c6x/crti.S17
-rw-r--r--libc/sysdeps/linux/c6x/crtn.S19
-rw-r--r--libc/sysdeps/linux/c6x/prctl.c43
-rw-r--r--libc/sysdeps/linux/c6x/pread_write.c103
-rw-r--r--libc/sysdeps/linux/c6x/setjmp.s43
-rw-r--r--libc/sysdeps/linux/c6x/sigaction.c115
-rw-r--r--libc/sysdeps/linux/c6x/sys/procfs.h122
-rw-r--r--libc/sysdeps/linux/c6x/sys/reg.h26
-rw-r--r--libc/sysdeps/linux/c6x/sys/ucontext.h39
-rw-r--r--libc/sysdeps/linux/c6x/sys/user.h28
-rw-r--r--libc/sysdeps/linux/c6x/syscall.c49
-rw-r--r--libc/sysdeps/linux/c6x/vfork.c26
-rw-r--r--libc/sysdeps/linux/common/Makefile.in1
-rw-r--r--libpthread/linuxthreads.old/sysdeps/c6x/pt-machine.h64
52 files changed, 3486 insertions, 0 deletions
diff --git a/Rules.mak b/Rules.mak
index fe287335b..0727e362a 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -218,10 +218,12 @@ ifeq ($(UCLIBC_HAS_SOFT_FLOAT),y)
ifneq ($(TARGET_ARCH),nios)
ifneq ($(TARGET_ARCH),nios2)
ifneq ($(TARGET_ARCH),sh)
+ifneq ($(TARGET_ARCH),c6x)
CPU_CFLAGS-y += -msoft-float
endif
endif
endif
+endif
ifeq ($(TARGET_ARCH),arm)
# No longer needed with current toolchains, but leave it here for now.
# If anyone is actually still using gcc 2.95 (say), they can uncomment it.
@@ -239,6 +241,7 @@ CPU_LDFLAGS-$(ARCH_BIG_ENDIAN) += -Wl,-EB
PICFLAG-y := -fPIC
PICFLAG-$(UCLIBC_FORMAT_FDPIC_ELF) := -mfdpic
+PICFLAG-$(UCLIBC_FORMAT_DSBT_ELF) := -mdsbt -fpic
PICFLAG := $(PICFLAG-y)
PIEFLAG_NAME:=-fPIE
@@ -485,6 +488,15 @@ ifeq ($(TARGET_ARCH),v850)
SYMBOL_PREFIX=_
endif
+ifeq ($(TARGET_ARCH),c6x)
+ PIEFLAG:=
+ CPU_CFLAGS-$(CONFIG_TMS320C64X) += -march=c64x
+ CPU_CFLAGS-$(CONFIG_TMS320C64XPLUS) += -march=c64x+
+ CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN)+=-mlittle-endian
+ CPU_CFLAGS-$(ARCH_BIG_ENDIAN)+=-mbig-endian
+ CPU_LDFLAGS-y += $(CPU_CFLAGS)
+endif
+
# Keep the check_gcc from being needlessly executed
ifndef PIEFLAG
export PIEFLAG:=$(call check_gcc,$(PIEFLAG_NAME),$(PICFLAG))
diff --git a/extra/Configs/Config.c6x b/extra/Configs/Config.c6x
new file mode 100644
index 000000000..d71df3f14
--- /dev/null
+++ b/extra/Configs/Config.c6x
@@ -0,0 +1,34 @@
+#
+# For a description of the syntax of this configuration file,
+# see extra/config/Kconfig-language.txt
+#
+
+config TARGET_ARCH
+ default "c6x"
+
+config FORCE_OPTIONS_FOR_ARCH
+ bool
+ default y
+ select ARCH_ANY_ENDIAN
+
+config ARCH_CFLAGS
+ string
+
+config ARCH_LDFLAGS
+ string
+
+choice
+ prompt "Target Processor Type"
+ default CONFIG_GENERIC_C6X
+
+config CONFIG_GENERIC_C6X
+ bool "Generic C6X DSP"
+
+config CONFIG_TMS320C64X
+ bool "TMS320C64X"
+
+config CONFIG_TMS320C64XPLUS
+ bool "TMS320C64X+"
+
+endchoice
+
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index 4d2c870bd..8628f28f6 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -114,6 +114,9 @@ config TARGET_x86_64
config TARGET_xtensa
bool "xtensa"
+config TARGET_c6x
+ bool "c6x"
+
endchoice
@@ -219,6 +222,10 @@ if TARGET_xtensa
source "extra/Configs/Config.xtensa"
endif
+if TARGET_c6x
+source "extra/Configs/Config.c6x"
+endif
+
config TARGET_SUBARCH
string
default "e500" if CONFIG_E500
diff --git a/extra/Configs/Config.in.arch b/extra/Configs/Config.in.arch
index 068bccc69..5f7a2b0c6 100644
--- a/extra/Configs/Config.in.arch
+++ b/extra/Configs/Config.in.arch
@@ -17,6 +17,10 @@ config UCLIBC_FORMAT_FDPIC_ELF
bool "FDPIC ELF"
depends on !ARCH_USE_MMU && (TARGET_bfin || TARGET_frv)
select DOPIC
+config UCLIBC_FORMAT_DSBT_ELF
+ bool "DBST ELF"
+ depends on !ARCH_USE_MMU && TARGET_c6x
+ select DOPIC
config UCLIBC_FORMAT_FLAT
bool "STATIC FLAT"
depends on !ARCH_USE_MMU
diff --git a/include/elf.h b/include/elf.h
index b86aa52be..d71691eb3 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -268,6 +268,7 @@ typedef struct
#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */
#define EM_CRX 114 /* National Semiconductor CRX */
#define EM_NUM 95
+#define EM_TI_C6000 140
/* If it is necessary to assign new unofficial EM_* values, please pick large
random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision
@@ -3063,6 +3064,50 @@ typedef Elf32_Addr Elf32_Conflict;
/* Keep this the last entry. */
#define R_XTENSA_NUM 50
+/* C6X specific relocs */
+#define R_C6000_NONE 0
+#define R_C6000_ABS32 1
+#define R_C6000_ABS16 2
+#define R_C6000_ABS8 3
+#define R_C6000_PCR_S21 4
+#define R_C6000_PCR_S12 5
+#define R_C6000_PCR_S10 6
+#define R_C6000_PCR_S7 7
+#define R_C6000_ABS_S16 8
+#define R_C6000_ABS_L16 9
+#define R_C6000_ABS_H16 10
+#define R_C6000_SBR_U15_B 11
+#define R_C6000_SBR_U15_H 12
+#define R_C6000_SBR_U15_W 13
+#define R_C6000_SBR_S16 14
+#define R_C6000_SBR_L16_B 15
+#define R_C6000_SBR_L16_H 16
+#define R_C6000_SBR_L16_W 17
+#define R_C6000_SBR_H16_B 18
+#define R_C6000_SBR_H16_H 19
+#define R_C6000_SBR_H16_W 20
+#define R_C6000_SBR_GOT_U15_W 21
+#define R_C6000_SBR_GOT_L16_W 22
+#define R_C6000_SBR_GOT_H16_W 23
+#define R_C6000_DSBT_INDEX 24
+#define R_C6000_PREL31 25
+#define R_C6000_COPY 26
+#define R_C6000_JUMP_SLOT 27
+#define R_C6000_SBR_GOT32 28
+#define R_C6000_PCR_H16 29
+#define R_C6000_PCR_L16 30
+#define R_C6000_ALIGN 253
+#define R_C6000_FPHEAD 254
+#define R_C6000_NOCMP 255
+
+/* C6x specific values for the Dyn d_tag field. */
+#define DT_C6000_DSBT_BASE (DT_LOPROC + 0)
+#define DT_C6000_DSBT_SIZE (DT_LOPROC + 1)
+#define DT_C6000_PREEMPTMAP (DT_LOPROC + 2)
+#define DT_C6000_DSBT_INDEX (DT_LOPROC + 3)
+
+#define DT_C6000_NUM 4
+
#ifdef __cplusplus
}
#endif
diff --git a/ldso/ldso/c6x/dl-debug.h b/ldso/ldso/c6x/dl-debug.h
new file mode 100644
index 000000000..9c6edab0a
--- /dev/null
+++ b/ldso/ldso/c6x/dl-debug.h
@@ -0,0 +1,49 @@
+/* C6X DSBT ELF shared library loader suppport.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * All rights reserved.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+static const char *_dl_reltypes_tab[] =
+{
+ "R_C6000_NONE", /* 0 */
+ "R_C6000_ABS32",
+ "R_C6000_ABS16",
+ "R_C6000_ABS8",
+ "R_C6000_PCR_S21",
+ "R_C6000_PCR_S12", /* 5 */
+ "R_C6000_PCR_S10",
+ "R_C6000_PCR_S7",
+ "R_C6000_ABS_S16",
+ "R_C6000_ABS_L16",
+ "R_C6000_ABS_H16", /* 10 */
+ "R_C6000_SBR_U15_B",
+ "R_C6000_SBR_U15_H",
+ "R_C6000_SBR_U15_W",
+ "R_C6000_SBR_S16",
+ "R_C6000_SBR_L16_B", /* 15 */
+ "R_C6000_SBR_L16_H",
+ "R_C6000_SBR_L16_W",
+ "R_C6000_SBR_H16_B",
+ "R_C6000_SBR_H16_H",
+ "R_C6000_SBR_H16_W", /* 20 */
+ "R_C6000_SBR_GOT_U15_W",
+ "R_C6000_SBR_GOT_L16_W",
+ "R_C6000_SBR_GOT_H16_W",
+ "R_C6000_DSBT_INDEX",
+ "R_C6000_PREL31", /* 25 */
+ "R_C6000_COPY",
+ "R_C6000_JUMP_SLOT",
+ "R_C6000_SBR_GOT32",
+ "R_C6000_PCR_H16",
+ "R_C6000_PCR_L16", /* 30 */
+#if 0
+ "R_C6000_ALIGN", /* 253 */
+ "R_C6000_FPHEAD", /* 254 */
+ "R_C6000_NOCMP", /* 255 */
+#endif
+};
diff --git a/ldso/ldso/c6x/dl-inlines.h b/ldso/ldso/c6x/dl-inlines.h
new file mode 100644
index 000000000..d8fb42c55
--- /dev/null
+++ b/ldso/ldso/c6x/dl-inlines.h
@@ -0,0 +1,91 @@
+/* Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Borrowed heavily from frv arch:
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Figure out whether the given address is in one of the mapped
+ segments. */
+static __always_inline int
+__dl_addr_in_loadaddr (void *p, struct elf32_dsbt_loadaddr loadaddr)
+{
+ struct elf32_dsbt_loadmap *map = loadaddr.map;
+ int c;
+
+ for (c = 0; c < map->nsegs; c++)
+ if ((void*)map->segs[c].addr <= p
+ && (char*)p < (char*)map->segs[c].addr + map->segs[c].p_memsz)
+ return 1;
+
+ return 0;
+}
+
+/* Figure out how many LOAD segments there are in the given headers,
+ and allocate a block for the load map big enough for them.
+ got_value will be properly initialized later on, with INIT_GOT. */
+static __always_inline int
+__dl_init_loadaddr (struct elf32_dsbt_loadaddr *loadaddr, Elf32_Phdr *ppnt,
+ int pcnt)
+{
+ int count = 0, i;
+ size_t size;
+
+ for (i = 0; i < pcnt; i++)
+ if (ppnt[i].p_type == PT_LOAD)
+ count++;
+
+ size = sizeof (struct elf32_dsbt_loadmap)
+ + sizeof (struct elf32_dsbt_loadseg) * count;
+ loadaddr->map = _dl_malloc (size);
+ if (! loadaddr->map)
+ _dl_exit (-1);
+
+ loadaddr->map->version = 0;
+ loadaddr->map->nsegs = 0;
+
+ return count;
+}
+
+/* Incrementally initialize a load map. */
+static __always_inline void
+__dl_init_loadaddr_hdr (struct elf32_dsbt_loadaddr loadaddr, void *addr,
+ Elf32_Phdr *phdr, int maxsegs)
+{
+ struct elf32_dsbt_loadseg *segdata;
+
+ if (loadaddr.map->nsegs == maxsegs)
+ _dl_exit (-1);
+
+ segdata = &loadaddr.map->segs[loadaddr.map->nsegs++];
+ segdata->addr = (Elf32_Addr) addr;
+ segdata->p_vaddr = phdr->p_vaddr;
+ segdata->p_memsz = phdr->p_memsz;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ {
+ if (_dl_debug)
+ _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
+ loadaddr.map->nsegs-1,
+ segdata->p_vaddr, segdata->addr, segdata->p_memsz);
+ }
+#endif
+}
+
+static __always_inline void
+__dl_loadaddr_unmap (struct elf32_dsbt_loadaddr loadaddr)
+{
+ int i;
+
+ for (i = 0; i < loadaddr.map->nsegs; i++)
+ _dl_munmap ((void*)loadaddr.map->segs[i].addr,
+ loadaddr.map->segs[i].p_memsz);
+
+ /* _dl_unmap is only called for dlopen()ed libraries, for which
+ calling free() is safe, or before we've completed the initial
+ relocation, in which case calling free() is probably pointless,
+ but still safe. */
+ _dl_free (loadaddr.map);
+}
diff --git a/ldso/ldso/c6x/dl-startup.h b/ldso/ldso/c6x/dl-startup.h
new file mode 100644
index 000000000..b9ea30409
--- /dev/null
+++ b/ldso/ldso/c6x/dl-startup.h
@@ -0,0 +1,122 @@
+/* Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Borrowed heavily from frv arch:
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#undef DL_START
+#define DL_START(X) \
+int \
+_dl_start (unsigned placeholder, \
+ struct elf32_dsbt_loadmap *dl_boot_progmap, \
+ struct elf32_dsbt_loadmap *dl_boot_ldsomap, \
+ Elf32_Dyn *dl_boot_ldso_dyn_pointer, \
+ X)
+
+/*
+ * On entry, the kernel has set up the stack thusly:
+ *
+ * 0(sp) pad0
+ * 4(sp) pad1
+ * 8(sp) argc
+ * 12(sp) argv[0]
+ * ...
+ * (4*(argc+3))(sp) NULL
+ * (4*(argc+4))(sp) envp[0]
+ * ...
+ * NULL
+ *
+ * Register values are unspecified, except:
+ *
+ * B4 --> executable loadmap address
+ * A6 --> interpreter loadmap address
+ * B6 --> dynamic section address
+ * B14 --> our DP setup by kernel
+ *
+ * NB: DSBT index is always 0 for the executable
+ * and 1 for the interpreter
+ */
+
+__asm__(" .text\n"
+ ".globl _start\n"
+ "_start:\n"
+ " B .S2 _dl_start\n"
+ " STW .D2T2 B14, *+B14[1]\n"
+ " ADD .D1X B15,8,A8\n"
+ " ADDKPC .S2 ret_from_dl,B3,2\n"
+ "ret_from_dl:\n"
+ " B .S2X A4\n"
+ " || LDW .D2T2 *+B14[0],B14\n"
+ " ADDKPC .S2 __dl_fini,B0,0\n"
+ " MV .S1X B0,A4\n"
+ " NOP\n"
+ " NOP\n"
+ " NOP\n"
+ "__dl_fini:\n"
+ " LDW .D2T2 *+B14[1],B14\n"
+ " NOP 4\n"
+ " LDW .D2T1 *+B14($GOT(_dl_fini)), A0\n"
+ " NOP 4\n"
+ " BNOP .S2X A0, 5\n");
+
+__asm__(" .text\n"
+ "__c6x_cache_sync:\n"
+ " MVK .S2 330,B0\n"
+ " SWE\n"
+ " NOP\n"
+ " BNOP .S2 B3,5\n"
+ " NOP\n"
+ " NOP\n"
+ " NOP\n"
+ " NOP\n"
+ "\n"
+);
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS) + 1)
+
+struct elf32_dsbt_loadmap;
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader. RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+ switch(ELF32_R_TYPE((RELP)->r_info)){ \
+ case R_C6000_ABS_L16: \
+ { \
+ unsigned int opcode = *(REL); \
+ unsigned int v = (SYMBOL) + (RELP)->r_addend; \
+ opcode &= ~0x7fff80; \
+ opcode |= ((v & 0xffff) << 7); \
+ *(REL) = opcode; \
+ } \
+ break; \
+ case R_C6000_ABS_H16: \
+ { \
+ unsigned int opcode = *(REL); \
+ unsigned int v = (SYMBOL) + (RELP)->r_addend; \
+ opcode &= ~0x7fff80; \
+ opcode |= ((v >> 9) & 0x7fff80); \
+ *(REL) = opcode; \
+ } \
+ break; \
+ case R_C6000_ABS32: \
+ *(REL) = (SYMBOL) + (RELP)->r_addend; \
+ break; \
+ default: \
+ _dl_exit(1); \
+ }
+
+extern void __c6x_cache_sync(unsigned long start, unsigned long end)
+ attribute_hidden;
diff --git a/ldso/ldso/c6x/dl-syscalls.h b/ldso/ldso/c6x/dl-syscalls.h
new file mode 100644
index 000000000..9ff3358b0
--- /dev/null
+++ b/ldso/ldso/c6x/dl-syscalls.h
@@ -0,0 +1,25 @@
+/* Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
+#include "sys/syscall.h"
+extern int _dl_errno;
+#undef __set_errno
+#define __set_errno(X) {(_dl_errno) = (X);}
+#include <sys/mman.h>
+
+#ifdef __NR_pread64
+#define __NR___syscall_pread __NR_pread64
+static __always_inline _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
+ size_t, count, off_t, offset_hi, off_t, offset_lo);
+
+static __always_inline ssize_t
+_dl_pread(int fd, void *buf, size_t count, off_t offset)
+{
+ return(__syscall_pread(fd,buf,count, offset, offset >> 31));
+}
+#endif
diff --git a/ldso/ldso/c6x/dl-sysdep.h b/ldso/ldso/c6x/dl-sysdep.h
new file mode 100644
index 000000000..8f1b122d3
--- /dev/null
+++ b/ldso/ldso/c6x/dl-sysdep.h
@@ -0,0 +1,209 @@
+/* Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Borrowed heavily from frv arch:
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <bits/elf-dsbt.h>
+
+/*
+ * Define this if the system uses RELOCA.
+ */
+#define ELF_USES_RELOCA 1
+
+/* JMPREL relocs are inside the DT_RELA table. */
+/* Actually looks like a linker bug sets DT_JMPREL anyway */
+#define ELF_MACHINE_PLTREL_OVERLAP 1
+
+#undef DL_NO_COPY_RELOCS
+
+#define HAVE_DL_INLINES_H
+
+
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/* Initialization sequence for the GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+}
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_TI_C6000
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "C6000"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+struct elf_resolve;
+
+extern int _dl_linux_resolve(void) attribute_hidden;
+
+struct funcdesc_ht;
+struct elf32_dsbt_loadaddr;
+
+/* We must force strings used early in the bootstrap into the text
+ segment (const data), such that they are referenced relative to
+ the DP register rather than through the GOT which will not have
+ been relocated when these are used. */
+#undef SEND_EARLY_STDERR
+#define SEND_EARLY_STDERR(S) \
+ do { static char __s[] = (S); SEND_STDERR (__s); } while (0)
+
+#define DL_LOADADDR_TYPE struct elf32_dsbt_loadaddr
+
+#define DL_RELOC_ADDR(LOADADDR, ADDR) \
+ ((ElfW(Addr))__reloc_pointer ((void*)(ADDR), (LOADADDR).map))
+
+#define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \
+ do { \
+ struct elf32_dsbt_loadmap *map; \
+ map = dl_boot_ldsomap ?: dl_boot_progmap; \
+ if (map->version != 0) { \
+ SEND_EARLY_STDERR ("Invalid loadmap version number\n"); \
+ _dl_exit(-1); \
+ } \
+ if (map->nsegs < 2) { \
+ SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); \
+ _dl_exit(-1); \
+ } \
+ (LOADADDR).map = map; \
+ } while(0)
+
+#define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \
+ do { \
+ if (dl_boot_progmap->version != 0) { \
+ SEND_EARLY_STDERR ("Invalid loadmap version number\n"); \
+ _dl_exit(-1); \
+ } \
+ if (dl_boot_progmap->nsegs < 2) { \
+ SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); \
+ _dl_exit(-1); \
+ } \
+ (LOADADDR).map = dl_boot_progmap; \
+ } while(0)
+
+#define DL_INIT_LOADADDR_EXTRA_DECLS \
+ int dl_init_loadaddr_load_count;
+
+#define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \
+ (dl_init_loadaddr_load_count = \
+ __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT)))
+
+#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+ (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
+ dl_init_loadaddr_load_count))
+
+#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
+ (__dl_loadaddr_unmap ((LOADADDR)))
+
+#define DL_LIB_UNMAP(LIB, LEN) \
+ (__dl_loadaddr_unmap ((LIB)->loadaddr))
+
+#define DL_LOADADDR_BASE(LOADADDR) \
+ ((LOADADDR).map->dsbt_table)
+
+#define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \
+ (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr))
+
+
+/* We only support loading DSBT relocatable shared libraries.
+ It probably wouldn't be too hard to support loading statically
+ linked executables that require relocation.*/
+#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \
+do \
+{ \
+ (piclib) = 2; \
+} \
+while (0)
+
+/* We want want to apply all relocations in the interpreter during
+ bootstrap. Because of this, we have to skip the interpreter
+ relocations in _dl_parse_relocation_information(), see
+ elfinterp.c. */
+#define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0
+
+#ifdef __NR_pread64
+#define _DL_PREAD(FD, BUF, SIZE, OFFSET) \
+ (_dl_pread((FD), (BUF), (SIZE), (OFFSET)))
+#endif
+
+#define DL_GET_READY_TO_RUN_EXTRA_PARMS \
+ , struct elf32_dsbt_loadmap *dl_boot_progmap \
+ , struct elf32_dsbt_loadmap *dl_boot_ldsomap
+#define DL_GET_READY_TO_RUN_EXTRA_ARGS \
+ , dl_boot_progmap \
+ , dl_boot_ldsomap
+
+
+/*
+ * Compute the GOT address.
+ * Also setup program and interpreter DSBT table entries.
+ */
+#define DL_BOOT_COMPUTE_GOT(GOT) \
+ do { \
+ unsigned long *ldso_dsbt, *prog_dsbt; \
+ ldso_dsbt = dl_boot_ldsomap->dsbt_table; \
+ prog_dsbt = dl_boot_progmap->dsbt_table; \
+ ldso_dsbt[0] = prog_dsbt[0] = (unsigned long)prog_dsbt; \
+ ldso_dsbt[1] = prog_dsbt[1] = (unsigned long)ldso_dsbt; \
+ (GOT) = ldso_dsbt + dl_boot_ldsomap->dsbt_size; \
+ } while(0)
+
+#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \
+ ((dpnt) = dl_boot_ldso_dyn_pointer)
+
+
+#ifdef __USE_GNU
+# include <link.h>
+#else
+# define __USE_GNU
+# include <link.h>
+# undef __USE_GNU
+#endif
+
+static __always_inline Elf32_Addr
+elf_machine_load_address (void)
+{
+ /* this is never an issue on DSBT systems */
+ return 0;
+}
+
+static __always_inline void
+elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+}
+
+/* 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
+ of the main executable's symbols, as for a COPY reloc. */
+#define elf_machine_type_class(type) \
+ ((((type) == R_C6000_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \