[PATCH v2 1/2] Initial PRU port
Dimitar Dimitrov <[email protected]>
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
Hi, I would like to contribute newlib port for the TI PRU I/O processor [1] [2]. Binutils and GCC ports have already been merged. The following files need to be regenerated. Let me know if I should post a separate patch for them: configure libgloss/configure libgloss/pru/aclocal.m4 libgloss/pru/configure newlib/libc/machine/configure newlib/libc/machine/pru/Makefile.in newlib/libc/machine/pru/aclocal.m4 newlib/libc/machine/pru/configure newlib/libm/machine/configure newlib/libm/machine/pru/Makefile.in newlib/libm/machine/pru/aclocal.m4 newlib/libm/machine/pru/configure Regards, Dimitar [1] http://processors.wiki.ti.com/index.php/PRU-ICSS [2] http://beagleboard.org/pru [3] https://sourceware.org/ml/newlib/2018/msg00392.html Signed-off-by: Dimitar Dimitrov <[email protected]> --- configure.ac | 4 + libgloss/configure.in | 3 + libgloss/pru/Makefile.in | 142 ++++++++++++++++ libgloss/pru/configure.in | 66 ++++++++ libgloss/pru/crt0.S | 84 ++++++++++ libgloss/pru/device-specs/sim | 5 + libgloss/pru/do_global_dtors.c | 40 +++++ libgloss/pru/gettimeofday.c | 31 ++++ libgloss/pru/inbyte.c | 38 +++++ libgloss/pru/isatty.c | 26 +++ libgloss/pru/ldscripts/gen-ld-scripts.sh | 55 +++++++ libgloss/pru/ldscripts/pruelf-sim.x | 200 +++++++++++++++++++++++ libgloss/pru/outbyte.c | 24 +++ libgloss/pru/print.c | 25 +++ libgloss/pru/putnum.c | 42 +++++ libgloss/pru/raise.c | 24 +++ libgloss/pru/sbrk.c | 46 ++++++ libgloss/pru/stat.c | 31 ++++ libgloss/pru/syscalls.S | 65 ++++++++ newlib/configure.host | 14 +- newlib/libc/include/machine/ieeefp.h | 4 + newlib/libc/include/machine/setjmp.h | 5 + newlib/libc/machine/configure.in | 1 + newlib/libc/machine/pru/Makefile.am | 16 ++ newlib/libc/machine/pru/configure.in | 14 ++ newlib/libc/machine/pru/setjmp.s | 46 ++++++ 26 files changed, 1050 insertions(+), 1 deletion(-) create mode 100644 libgloss/pru/Makefile.in create mode 100644 libgloss/pru/configure.in create mode 100644 libgloss/pru/crt0.S create mode 100644 libgloss/pru/device-specs/sim create mode 100644 libgloss/pru/do_global_dtors.c create mode 100644 libgloss/pru/gettimeofday.c create mode 100644 libgloss/pru/inbyte.c create mode 100644 libgloss/pru/isatty.c create mode 100755 libgloss/pru/ldscripts/gen-ld-scripts.sh create mode 100644 libgloss/pru/ldscripts/pruelf-sim.x create mode 100644 libgloss/pru/outbyte.c create mode 100644 libgloss/pru/print.c create mode 100644 libgloss/pru/putnum.c create mode 100644 libgloss/pru/raise.c create mode 100644 libgloss/pru/sbrk.c create mode 100644 libgloss/pru/stat.c create mode 100644 libgloss/pru/syscalls.S create mode 100644 newlib/libc/machine/pru/Makefile.am create mode 100644 newlib/libc/machine/pru/configure.in create mode 100644 newlib/libc/machine/pru/setjmp.s diff --git a/configure.ac b/configure.ac index cf856e567..28e83a73d 100644 --- a/configure.ac +++ b/configure.ac @@ -697,6 +697,10 @@ case "${target}" in powerpc-*-aix* | rs6000-*-aix*) noconfigdirs="$noconfigdirs target-libssp" ;; + pru-*-*) + # No hosted I/O support. + noconfigdirs="$noconfigdirs target-libssp" + ;; rl78-*-*) # libssp uses a misaligned load to trigger a fault, but the RL78 # doesn't fault for those - instead, it gives a build-time error diff --git a/libgloss/configure.in b/libgloss/configure.in index 41843eed1..a681f233f 100644 --- a/libgloss/configure.in +++ b/libgloss/configure.in @@ -176,6 +176,9 @@ case "${target}" in or1k-*-* | or1knd-*-* ) AC_CONFIG_SUBDIRS([or1k]) ;; + pru-*-*) + AC_CONFIG_SUBDIRS([pru]) + ;; nios2-*-*) AC_CONFIG_SUBDIRS([nios2]) ;; diff --git a/libgloss/pru/Makefile.in b/libgloss/pru/Makefile.in new file mode 100644 index 000000000..c15ea3eb4 --- /dev/null +++ b/libgloss/pru/Makefile.in @@ -0,0 +1,142 @@ +# Copyright (c) 2014-2019 Dimitar Dimitrov <[email protected]> +# +# The authors hereby grant permission to use, copy, modify, distribute, +# and license this software and its documentation for any purpose, provided +# that existing copyright notices are retained in all copies and that this +# notice is included verbatim in any distributions. No written agreement, +# license, or royalty fee is required for any of the authorized uses. +# Modifications to this software may be copyrighted by their authors +# and need not follow the licensing terms described here, provided that +# the new terms are clearly indicated on the first page of each file where +# they apply. + +VPATH = @srcdir@ @srcdir@/.. + +srcdir = @srcdir@ +objdir = . +srcroot = $(srcdir)/../.. +objroot = $(objdir)/../.. +top_srcdir = @top_srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +host_alias = @host_alias@ +target_alias = @target_alias@ + +bindir = @bindir@ +libdir = @libdir@ +includedir = @includedir@ +tooldir = $(exec_prefix)/$(target_alias) + +# Multilib support variables. +# TOP is used instead of MULTI{BUILD,SRC}TOP. +MULTIDIRS = +MULTISUBDIR = + +SHELL = /bin/sh + +mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs + +CC = @CC@ + +AS = @AS@ + +AR = @AR@ + +LD = @LD@ + +RANLIB = @RANLIB@ + +OBJDUMP = `t='$(program_transform_name)'; echo objdump | sed -e $$t` +OBJCOPY = `t='$(program_transform_name)'; echo objcopy | sed -e $$t` + +# linker scripts +SCRIPTS = `ls ${srcdir}/ldscripts/*.x` + +# object files needed +OBJS = \ + do_global_dtors.o gettimeofday.o \ + isatty.o putnum.o raise.o \ + inbyte.o outbyte.o sbrk.o stat.o syscalls.o \ + do_global_dtors.o + +# Object files specific to particular targets. +EVALOBJS = ${OBJS} + +CRTOBJS = crt0.o crt0-minrt.o +OUTPUTS = libgloss.a $(CRTOBJS) + +INCLUDES = -I$(srcdir)/.. + +# Note that when building the library, ${MULTILIB} is not the way multilib +# options are passed; they're passed in $(CFLAGS). +CFLAGS_FOR_TARGET = ${MULTILIB} ${INCLUDES} +LDFLAGS_FOR_TARGET = ${MULTILIB} + +.c.o: + $(CC) $(CFLAGS_FOR_TARGET) -Os $(INCLUDES) -c $(CFLAGS) $< + +.C.o: + $(CC) $(CFLAGS_FOR_TARGET) -Os $(INCLUDES) -c $(CFLAGS) $< +.s.o: + $(AS) $(ASFLAGS_FOR_TARGET) $(INCLUDES) $(ASFLAGS) -o $*.o $< + +# +# GCC knows to run the preprocessor on .S files before it assembles them. +# +.S.o: + $(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) $(CFLAGS) -c $< + +all: ${OUTPUTS} copy_scripts_to_objdir + +copy_scripts_to_objdir: $(srcdir)/ldscripts/gen-ld-scripts.sh + cp $(SCRIPTS) $(objdir) + +# +# here's where we build the library for each target +# + +libgloss.a: $(EVALOBJS) + ${AR} ${ARFLAGS} $@ $(EVALOBJS) + ${RANLIB} $@ + +# C Runtime Library startup code. +crt0.o: $(srcdir)/crt0.S + $(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) $(CFLAGS) $< -c -o $@ + +crt0-minrt.o: $(srcdir)/crt0.S + $(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) $(CFLAGS) -DMINRT $< -c -o $@ + +doc: + +clean mostlyclean: + rm -f $(OUTPUTS) *.i *~ *.o *-test *.srec *.dis *.map *.x + +distclean maintainer-clean realclean: clean + rm -f Makefile config.status $(OUTPUTS) + +.PHONY: install info install-info clean-info +install: $(OUTPUTS) $(srcdir)/ldscripts/gen-ld-scripts.sh + for outputs in ${OUTPUTS}; do\ + ${INSTALL_DATA} $${outputs} ${DESTDIR}${tooldir}/lib${MULTISUBDIR}/$${outputs}; \ + done + for s in $(SCRIPTS); do \ + b=`basename $$s`; \ + ${INSTALL_DATA} $$s ${DESTDIR}${tooldir}/lib${MULTISUBDIR}/$$b ;\ + done + ${mkinstalldirs} ${DESTDIR}${tooldir}/lib${MULTISUBDIR}/device-specs; \ + for s in ${srcdir}/device-specs/*; do \ + b=`basename $$s`; \ + $(INSTALL_DATA) $$s $(DESTDIR)$(tooldir)/lib${MULTISUBDIR}/device-specs/$$b ;\ + done + +info: +install-info: +clean-info: + +Makefile: $(srcdir)/Makefile.in config.status @host_makefile_frag_path@ + $(SHELL) config.status + +config.status: $(srcdir)/configure + $(SHELL) config.status --recheck diff --git a/libgloss/pru/configure.in b/libgloss/pru/configure.in new file mode 100644 index 000000000..2a4c946e8 --- /dev/null +++ b/libgloss/pru/configure.in @@ -0,0 +1,66 @@ +# Copyright (c) 2008, 2009, 2011, 2013 Red Hat, Inc. All rights reserved. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the BSD +# License. This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY expressed or implied, including the implied warranties +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. A copy of this license +# is available at http://www.opensource.org/licenses. Any Red Hat trademarks that +# are incorporated in the source code or documentation are not subject to the BSD +# License and may only be used or replicated with the express permission of +# Red Hat, Inc. + +dnl Process this file with autoconf to produce a configure script. +AC_PREREQ(2.59) +AC_INIT(crt0.S) + +if test "${enable_shared}" = "yes" ; then + echo "Shared libraries not supported for cross compiling, ignored" +fi + +if test "$srcdir" = "." ; then + if test "${with_target_subdir}" != "." ; then + libgloss_topdir="${srcdir}/${with_multisrctop}../../.." + else + libgloss_topdir="${srcdir}/${with_multisrctop}../.." + fi +else + libgloss_topdir="${srcdir}/../.." +fi +AC_CONFIG_AUX_DIR($libgloss_topdir) + +AC_CANONICAL_SYSTEM +AC_ARG_PROGRAM + +AC_PROG_INSTALL + +LIB_AC_PROG_CC +AS=${AS-as} +AC_SUBST(AS) +AR=${AR-ar} +AC_SUBST(AR) +LD=${LD-ld} +AC_SUBST(LD) +AC_PROG_RANLIB +LIB_AM_PROG_AS + +host_makefile_frag=${srcdir}/../config/default.mh + +dnl We have to assign the same value to other variables because autoconf +dnl doesn't provide a mechanism to substitute a replacement keyword with +dnl arbitrary data or pathnames. +dnl +host_makefile_frag_path=$host_makefile_frag +AC_SUBST(host_makefile_frag_path) +AC_SUBST_FILE(host_makefile_frag) + +AC_CONFIG_FILES(Makefile, +. ${libgloss_topdir}/config-ml.in, +srcdir=${srcdir} +target=${target} +with_multisubdir=${with_multisubdir} +ac_configure_args="${ac_configure_args} --enable-multilib" +CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} +libgloss_topdir=${libgloss_topdir} +) +AC_OUTPUT diff --git a/libgloss/pru/crt0.S b/libgloss/pru/crt0.S new file mode 100644 index 000000000..871ac72e2 --- /dev/null +++ b/libgloss/pru/crt0.S @@ -0,0 +1,84 @@ +/* crt0.S -- PRU startup code + * + * Copyright (c) 2014-2019 Dimitar Dimitrov <[email protected]> + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include "newlib.h" + + .extern main + .extern exit + + .text + .section .init0, "x" + .global _start +_start: + /* Initialize stack pointer. */ + ldi32 sp, _stack_top + + /* DATA and BSS are handled by the loader, so nothing to do here. */ + +#if !defined(MINRT) + .extern _do_global_dtors + /* Ensure destructors get called. Call is per GNU ABI (i.e. 32-bit + function pointers). But it is also compatible with the TI ABI + since GCC supports only little endian PRU. + + WARNING: Keep this compatible with both ABIs! */ + ldi r14, %pmem(_do_global_dtors) + call atexit + + /* Call constructors. Use non-call-clobbered registers. */ + ldi r5, __init_array_start + ldi r6, __init_array_end +ctors_loop: + qbeq ctors_done, r5, r6 + /* ABI dictates 16-bit IMEM pointers. */ + lbbo r7, r5, 0, 2 + call r7.w0 + add r5, r5, 2 + jmp ctors_loop +ctors_done: +#endif + + /* Just in case main() tries to access argc, argv[] and envp. */ + zero r14, 3 * 4 + +#if !defined(MINRT) + .weak __c_args__ + ldi32 r5, __c_args__ + qbeq __skip_c_args, r5, 0 + lbbo r14, r5, 0, 4 /* argc */ + add r15, r5, 4 /* argv */ +__skip_c_args: +#endif + + /* Call main */ + call main + +#if !defined(MINRT) + /* Call exit */ + call exit +#endif + + /* We should never reach here. */ +_crt_exit: + halt + jmp _crt_exit + + /* PRU obviously has no shared libraries, but dso_handle + helps to achieve better GCC test coverage. Besides, + it should be free with minrt. */ + .section .data + .global __dso_handle + .weak __dso_handle +__dso_handle: + .long 0 diff --git a/libgloss/pru/device-specs/sim b/libgloss/pru/device-specs/sim new file mode 100644 index 000000000..50d4689e0 --- /dev/null +++ b/libgloss/pru/device-specs/sim @@ -0,0 +1,5 @@ +*cpp_device: +-D__SIM__ + +*link_device: +%{!r:-Tpruelf-sim.x} diff --git a/libgloss/pru/do_global_dtors.c b/libgloss/pru/do_global_dtors.c new file mode 100644 index 000000000..3cc053ed5 --- /dev/null +++ b/libgloss/pru/do_global_dtors.c @@ -0,0 +1,40 @@ +/* do_global_dtors - invoke global destructors + * + * Copyright (c) 2015-2019 Dimitar Dimitrov <[email protected]> + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include <stdint.h> +#include <_ansi.h> +#include "syscall.h" + +extern void *__fini_array_start; +extern void *__fini_array_end; + +/* + * _do_global_dtors + */ +void +_do_global_dtors (void) +{ + /* ABI dictates pointers in init/fini arrays are 16-bit. */ + const uint16_t *end = (uint16_t *)&__fini_array_end; + const uint16_t *begin = (uint16_t *)&__fini_array_start; + const uint16_t *p; + void (**dtor) (void); + + /* call destructors in reverse order */ + for (p = end; p > begin; ) { + p--; + dtor = (void *)p; + (*dtor) (); + } +} diff --git a/libgloss/pru/gettimeofday.c b/libgloss/pru/gettimeofday.c new file mode 100644 index 000000000..b4b7cb078 --- /dev/null +++ b/libgloss/pru/gettimeofday.c @@ -0,0 +1,31 @@ +/* gettimeofday.c -- get the current time of day + * + * Copyright (c) 1995, 1999 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include <errno.h> +#include "glue.h" + +#undef errno +extern int errno; +struct timeval; + +/* + * gettimeofday -- no clock + * struct timeval * tp, void * tzvp + */ +int +_gettimeofday (struct timeval * tp, void * tzvp) +{ + errno = ENOSYS; + return -1; +} diff --git a/libgloss/pru/inbyte.c b/libgloss/pru/inbyte.c new file mode 100644 index 000000000..afb8fd927 --- /dev/null +++ b/libgloss/pru/inbyte.c @@ -0,0 +1,38 @@ +/* inbyte.c -- inbyte function for remoteproc + * + * Copyright (c) 2014-2019 Dimitar Dimitrov <[email protected]> + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include <errno.h> +#include <_ansi.h> +#include <stdio.h> +#include <unistd.h> +#include "glue.h" + +extern ssize_t _read(int fd, void *b, size_t count); + +int +inbyte (void) +{ + ssize_t n; + char c; + + /* PRU has no interrupts, so it is inherently thread-safe. */ + n = _read(STDIN_FILENO, &c, 1); + if (n < 0) + return n; + else if (n == 0) + return -ENODATA; + else + return 1; +} + diff --git a/libgloss/pru/isatty.c b/libgloss/pru/isatty.c new file mode 100644 index 000000000..bb160edf2 --- /dev/null +++ b/libgloss/pru/isatty.c @@ -0,0 +1,26 @@ +/* isatty.c -- chek the terminal device. + * + * Copyright (c) 1995 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include "glue.h" + +/* + * isatty -- returns 1 if connected to a terminal device, + * returns 0 if not. Since we're hooked up to a + * serial port, we'll say yes _AND return a 1. + */ +int +_isatty (int fd) +{ + return (1); +} diff --git a/libgloss/pru/ldscripts/gen-ld-scripts.sh b/libgloss/pru/ldscripts/gen-ld-scripts.sh new file mode 100755 index 000000000..c503232d7 --- /dev/null +++ b/libgloss/pru/ldscripts/gen-ld-scripts.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# Generate additional MCU-specific linker scripts by using the +# default PRU-LD linker script. +# +# We do it automatically so that: +# 1. We only change the default linker script in binutils. +# 2. All the default script complexity stays in binutils. +# 3. Here in libgloss we care only to enumerate all PRU variants with +# their default memory sizes. + +dump_modified() +{ + IMEM_SIZE=$1 + DMEM_SIZE=$2 + HEAP_SIZE=$3 + STACK_SIZE=$4 + + echo "/* WARNING: automatically generated from the default pru-ld script! */" + echo -e "\n\n" + pru-ld --verbose | awk " +BEGIN { LDV_MARKER = 0; } +{ + if (\$0 == \"==================================================\" ) + { + LDV_MARKER++; + } + else if (LDV_MARKER != 1) + { + } + else if (\$0 ~ /^ imem.*ORIGIN =.*LENGTH =/) + { + print \" imem (x) : ORIGIN = 0x20000000, LENGTH = $IMEM_SIZE\" + } + else if (\$0 ~ /^ dmem.*ORIGIN =.*LENGTH =/) + { + print \" dmem (rw!x) : ORIGIN = 0x0, LENGTH = $DMEM_SIZE\" + } + else if (\$0 ~ /^__HEAP_SIZE = DEFINED/) + { + print \"__HEAP_SIZE = DEFINED(__HEAP_SIZE) ? __HEAP_SIZE : $HEAP_SIZE ;\"; + } + else if (\$0 ~ /^__STACK_SIZE = DEFINED/) + { + print \"__STACK_SIZE = DEFINED(__STACK_SIZE) ? __STACK_SIZE : $STACK_SIZE ;\"; + } + else + { + print \$0; + } +}" +} + +# IMEM DMEM HEAP_SIZE STACK_SIZE +dump_modified 256K 65536K "32 * 1024 * 1024" "1024 * 1024" | tee pruelf-sim.x diff --git a/libgloss/pru/ldscripts/pruelf-sim.x b/libgloss/pru/ldscripts/pruelf-sim.x new file mode 100644 index 000000000..1dc8b4f2e --- /dev/null +++ b/libgloss/pru/ldscripts/pruelf-sim.x @@ -0,0 +1,200 @@ +/* WARNING: automatically generated from the default pru-ld script! */ + + + +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf32-pru","elf32-pru","elf32-pru") +OUTPUT_ARCH(pru) +MEMORY +{ + imem (x) : ORIGIN = 0x20000000, LENGTH = 256K + dmem (rw!x) : ORIGIN = 0x0, LENGTH = 65536K +} +__HEAP_SIZE = DEFINED(__HEAP_SIZE) ? __HEAP_SIZE : 32 * 1024 * 1024 ; +__STACK_SIZE = DEFINED(__STACK_SIZE) ? __STACK_SIZE : 1024 * 1024 ; +PROVIDE (_stack_top = ORIGIN(dmem) + LENGTH(dmem)); +ENTRY (_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : + { + *(.rel.text) + *(.rel.text.*) + *(.rel.text:*) + *(.rel.gnu.linkonce.t*) + } + .rela.text : + { + *(.rela.text) + *(.rela.text.*) + *(.rela.text:*) + *(.rela.gnu.linkonce.t*) + } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : + { + *(.rel.rodata) + *(.rel.rodata.*) + *(.rel.rodata:*) + *(.rel.gnu.linkonce.r*) + } + .rela.rodata : + { + *(.rela.rodata) + *(.rela.rodata.*) + *(.rela.rodata:*) + *(.rela.gnu.linkonce.r*) + } + .rel.data : + { + *(.rel.data) + *(.rel.data.*) + *(.rel.data:*) + *(.rel.gnu.linkonce.d*) + } + .rela.data : + { + *(.rela.data) + *(.rela.data.*) + *(.rela.data:*) + *(.rela.gnu.linkonce.d*) + } + .rel.init_array : { *(.rel.init_array) } + .rela.init_array : { *(.rela.init_array) } + .rel.fini_array : { *(.rel.fini_array) } + .rela.fini_array : { *(.rela.fini_array) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + /* Internal text space. */ + .text : + { + _text_start = . ; + . = ALIGN(4); + *(.init0) /* Start here after reset. */ + KEEP (*(.init0)) + . = ALIGN(4); + *(.text) + . = ALIGN(4); + *(.text.*) + . = ALIGN(4); + *(.text:*) + . = ALIGN(4); + *(.gnu.linkonce.t*) + . = ALIGN(4); + _text_end = . ; + } > imem + .data : + { + /* Optional variable that user is prepared to have NULL address. */ + *(.data.atzero*) + /* CRT is prepared for constructor/destructor table to have + a "valid" NULL address. */ + __init_array_start = . ; + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = . ; + __fini_array_start = . ; + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*))) + KEEP (*(.fini_array)) + __fini_array_end = . ; + /* DATA memory starts at address 0. So to avoid placing a valid static + variable at the invalid NULL address, we introduce the .data.atzero + section. If CRT can make some use of it - great. Otherwise skip a + word. In all cases .data/.bss sections must start at non-zero. */ + . += (. == 0 ? 4 : 0); + PROVIDE (_data_start = .) ; + *(.data) + *(.data*) + *(.data:*) + *(.rodata) /* We need to include .rodata here if gcc is used. */ + *(.rodata.*) /* with -fdata-sections. */ + *(.rodata:*) + *(.gnu.linkonce.d*) + *(.gnu.linkonce.r*) + . = ALIGN(4); + PROVIDE (_data_end = .) ; + } > dmem + .resource_table : + { + KEEP (*(.resource_table)) + } > dmem + .bss : + { + PROVIDE (_bss_start = .) ; + *(.bss) + *(.bss.*) + *(.bss:*) + *(.gnu.linkonce.b*) + *(COMMON) + PROVIDE (_bss_end = .) ; + } > dmem + /* Global data not cleared after reset. */ + .noinit : + { + PROVIDE (_noinit_start = .) ; + *(.noinit) + PROVIDE (_noinit_end = .) ; + PROVIDE (_heap_start = .) ; + . += __HEAP_SIZE ; + /* Stack is not here really. It will be put at the end of DMEM. + But we take into account its size here, in order to allow + for MEMORY overflow checking during link time. */ + . += __STACK_SIZE ; + } > dmem + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .debug_addr 0 : { *(.debug_addr) } +} + + diff --git a/libgloss/pru/outbyte.c b/libgloss/pru/outbyte.c new file mode 100644 index 000000000..a13f74f13 --- /dev/null +++ b/libgloss/pru/outbyte.c @@ -0,0 +1,24 @@ +/* outbyte.c -- outbyte function for simulator + * + * Copyright (c) 2014-2019 Dimitar Dimitrov <[email protected]> + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include <unistd.h> +#include <_ansi.h> + +extern ssize_t _write(int fd, const void *b, size_t count); + +void +outbyte (char ch) +{ + _write(STDOUT_FILENO, &ch, 1); +} diff --git a/libgloss/pru/print.c b/libgloss/pru/print.c new file mode 100644 index 000000000..00a40b387 --- /dev/null +++ b/libgloss/pru/print.c @@ -0,0 +1,25 @@ +/* print.c -- print a string on the output device. + * + * Copyright (c) 1995, 1999 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include <unistd.h> +#include "glue.h" + +/* + * print -- do a raw print of a string + */ +void +_print (char *ptr) +{ + _write(STDOUT_FILENO, ptr, strlen(ptr)); +} diff --git a/libgloss/pru/putnum.c b/libgloss/pru/putnum.c new file mode 100644 index 000000000..127e1c3dd --- /dev/null +++ b/libgloss/pru/putnum.c @@ -0,0 +1,42 @@ +/* putnum.c -- put a hex number on the output device. + * + * Copyright (c) 1995, 1999 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include "glue.h" + +extern void print (char *ptr); + +/* + * putnum -- print a 32 bit number in hex + */ +void +_putnum (unsigned int num) +{ + char buf[9]; + int cnt; + char *ptr; + int digit; + + ptr = buf; + for (cnt = 7 ; cnt >= 0 ; cnt--) { + digit = (num >> (cnt * 4)) & 0xf; + + if (digit <= 9) + *ptr++ = (char) ('0' + digit); + else + *ptr++ = (char) ('a' - 10 + digit); + } + + *ptr = (char) 0; + print (buf); +} diff --git a/libgloss/pru/raise.c b/libgloss/pru/raise.c new file mode 100644 index 000000000..d8e902605 --- /dev/null +++ b/libgloss/pru/raise.c @@ -0,0 +1,24 @@ +/* raise.c -- raise a signal for current process. + * + * Copyright (c) 1999 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include "glue.h" + +extern int _kill (int, int); +extern int _getpid(void); + +int +_raise (int sig) +{ + return _kill (_getpid (), sig); +} diff --git a/libgloss/pru/sbrk.c b/libgloss/pru/sbrk.c new file mode 100644 index 000000000..f14e4ec34 --- /dev/null +++ b/libgloss/pru/sbrk.c @@ -0,0 +1,46 @@ +/* sbrk.c -- allocate memory dynamically. + * + * Copyright (c) 1995,1996,1999 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include <sys/types.h> +#include <sys/stat.h> +#include "glue.h" + +extern char _heap_start[]; +extern void exit (int) __attribute ((__noreturn__)); +extern int _write (int, char *, int); + +caddr_t +_sbrk (size_t incr) +{ + static char *heap_end; + char *prev_heap_end; + char *sp = (char *)&sp; + + if (heap_end == 0) + { + heap_end = _heap_start; + } + prev_heap_end = heap_end; + if (heap_end > sp) + { + _write (1, "Heap and stack collision\n", 25); +#if 0 /* Calling abort brings in the signal handling code. */ + abort (); +#else + exit (1); +#endif + } + heap_end += incr; + return (caddr_t) prev_heap_end; +} diff --git a/libgloss/pru/stat.c b/libgloss/pru/stat.c new file mode 100644 index 000000000..64cb27253 --- /dev/null +++ b/libgloss/pru/stat.c @@ -0,0 +1,31 @@ +/* stat.c -- Get the status of a file. + * + * Copyright (c) 1995, 1999 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include <sys/stat.h> +#include <errno.h> +#include "glue.h" + +#undef errno +extern int errno; + +/* + * stat -- Since we have no file system, we just return an error. + */ +int +_stat (const char *path, struct stat *buf) +{ + errno = EIO; + return (-1); +} + diff --git a/libgloss/pru/syscalls.S b/libgloss/pru/syscalls.S new file mode 100644 index 000000000..153ab1708 --- /dev/null +++ b/libgloss/pru/syscalls.S @@ -0,0 +1,65 @@ +/* syscalls.S -- PRU system calls code + * + * Copyright (c) 2014-2019 Dimitar Dimitrov <[email protected]> + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include "newlib.h" + +#include "syscall.h" + + .extern _impure_ptr + + /* Handle return from syscall. */ + .global __SC_ret + .type __SC_ret,@function + .func +__SC_ret: + /* Check for negative return code */ + qbbc __SC_ret_skip_errno_set, r14, 31 + + /* Invert return code and store to errno (first int in _impure_ptr). */ + rsb r14, r14, 0 + ldi32 r1, _impure_ptr + sbbo r14, r1, 0, 4 + /* Return -1 (for both int32_t or int64_t). */ + fill r14, 8 + +__SC_ret_skip_errno_set: + ret + .endfunc + +.macro SC fname, id + .global \fname + .type \fname,@function + .func +\fname: + ldi r1, \id + halt + jmp __SC_ret + .endfunc +.endm + + .text + + /* Syscalls are used only by simulator. Real HW + users use other methods for communicating with + the host - remoteproc, rpmsg, shared memory. */ + SC _exit, SYS_exit + SC _open, SYS_open + SC _close, SYS_close + SC _read, SYS_read + SC _write, SYS_write + SC _lseek, SYS_lseek + SC _unlink, SYS_unlink + SC _getpid, SYS_getpid + SC _kill, SYS_kill + SC _fstat, SYS_fstat diff --git a/newlib/configure.host b/newlib/configure.host index 87bf78a3a..6a6066bb2 100644 --- a/newlib/configure.host +++ b/newlib/configure.host @@ -85,7 +85,7 @@ case "${target_optspace}:${host}" in yes:*) newlib_cflags="${newlib_cflags} -Os" ;; - :m32r-* | :d10v-* | :d30v-* | :avr-* | :m32c-* | :msp430*-* | :nds32* | :rl78-* ) + :m32r-* | :d10v-* | :d30v-* | :avr-* | :m32c-* | :msp430*-* | :nds32* | :pru-* | :rl78-* ) newlib_cflags="${newlib_cflags} -Os" ;; no:* | :*) @@ -289,6 +289,14 @@ case "${host_cpu}" in powerpc*) machine_dir=powerpc ;; + pru*) + newlib_cflags="${newlib_cflags} -DPREFER_SIZE_OVER_SPEED" + newlib_cflags="${newlib_cflags} -DNO_EXEC" + newlib_cflags="${newlib_cflags} -DSMALL_MEMORY" + default_newlib_nano_malloc="yes" + default_newlib_atexit_dynamic_alloc="no" + machine_dir=pru + ;; riscv*) libm_machine_dir=riscv machine_dir=riscv @@ -854,6 +862,10 @@ newlib_cflags="${newlib_cflags} -DCLOCK_PROVIDED -DMALLOC_PROVIDED -DEXIT_PROVID newlib_cflags="${newlib_cflags} -DHAVE_OPENDIR -DHAVE_RENAME -DHAVE_FCNTL -D_NO_POSIX_SPAWN" syscall_dir=syscalls ;; + pru*) + syscall_dir=syscalls + newlib_cflags="${newlib_cflags} -DSMALL_MEMORY -D_REENT_SMALL" + ;; riscv*-*-*) syscall_dir=syscalls ;; diff --git a/newlib/libc/include/machine/ieeefp.h b/newlib/libc/include/machine/ieeefp.h index 911eeb51e..536ac11fc 100644 --- a/newlib/libc/include/machine/ieeefp.h +++ b/newlib/libc/include/machine/ieeefp.h @@ -409,6 +409,10 @@ #define __SMALL_BITFIELDS /* 16 Bit INT */ #endif +#ifdef __PRU__ +#define __IEEE_LITTLE_ENDIAN +#endif + #ifdef __RL78__ #define __IEEE_LITTLE_ENDIAN #define __SMALL_BITFIELDS /* 16 Bit INT */ diff --git a/newlib/libc/include/machine/setjmp.h b/newlib/libc/include/machine/setjmp.h index 6b37bcce4..25fdea28c 100644 --- a/newlib/libc/include/machine/setjmp.h +++ b/newlib/libc/include/machine/setjmp.h @@ -352,6 +352,11 @@ _BEGIN_STD_C #define _JBTYPE unsigned long #endif +#ifdef __PRU__ +#define _JBLEN 48 +#define _JBTYPE unsigned int +#endif + #ifdef __RX__ #define _JBLEN 0x44 #endif diff --git a/newlib/libc/machine/configure.in b/newlib/libc/machine/configure.in index 0d4068c13..a070b5838 100644 --- a/newlib/libc/machine/configure.in +++ b/newlib/libc/machine/configure.in @@ -65,6 +65,7 @@ if test -n "${machine_dir}"; then nvptx) AC_CONFIG_SUBDIRS(nvptx) ;; or1k) AC_CONFIG_SUBDIRS(or1k) ;; powerpc) AC_CONFIG_SUBDIRS(powerpc) ;; + pru) AC_CONFIG_SUBDIRS(pru) ;; rl78) AC_CONFIG_SUBDIRS(rl78) ;; rx) AC_CONFIG_SUBDIRS(rx) ;; sh) AC_CONFIG_SUBDIRS(sh) ;; diff --git a/newlib/libc/machine/pru/Makefile.am b/newlib/libc/machine/pru/Makefile.am new file mode 100644 index 000000000..60885128d --- /dev/null +++ b/newlib/libc/machine/pru/Makefile.am @@ -0,0 +1,16 @@ +## Process this file with automake to generate Makefile.in + +AUTOMAKE_OPTIONS = cygnus + +INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) + +AM_CCASFLAGS = $(INCLUDES) + +noinst_LIBRARIES = lib.a + +lib_a_SOURCES = setjmp.s +lib_a_CCASFLAGS=$(AM_CCASFLAGS) +lib_a_CFLAGS=$(AM_CFLAGS) + +ACLOCAL_AMFLAGS = -I ../../.. -I ../../../.. +CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host diff --git a/newlib/libc/machine/pru/configure.in b/newlib/libc/machine/pru/configure.in new file mode 100644 index 000000000..d6eea0e9c --- /dev/null +++ b/newlib/libc/machine/pru/configure.in @@ -0,0 +1,14 @@ +dnl This is the newlib/libc/machine/pru configure.in file. +dnl Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) +AC_INIT([newlib],[NEWLIB_VERSION]) +AC_CONFIG_SRCDIR([setjmp.s]) + +dnl Can't be done in NEWLIB_CONFIGURE because that confuses automake. +AC_CONFIG_AUX_DIR(../../../..) + +NEWLIB_CONFIGURE(../../..) + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/newlib/libc/machine/pru/setjmp.s b/newlib/libc/machine/pru/setjmp.s new file mode 100644 index 000000000..46d950be6 --- /dev/null +++ b/newlib/libc/machine/pru/setjmp.s @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014-2019 Dimitar Dimitrov <[email protected]> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + .section .text + .align 3 + .globl setjmp + .type setjmp,@function + .globl longjmp + .type longjmp,@function + + +setjmp: + sbbo r2, r14, 0, 4*12 /* SP, RA, FP, r5-r13 */ + ldi r14, 0 + ret + +longjmp: + lbbo r2, r14, 0, 4*12 /* SP, RA, FP, r5-r13 */ + mov r14, r15 /* copy second arg to return location */ + qbne 1f, r14, 0 /* per stdC, we cannot return 0 */ + ldi r14, 1 +1: + ret -- 2.20.1