summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-01-21 14:58:17 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-01-21 14:58:17 +0100
commit5fa401dcd8bd6119ae9c0732123a7d03ab1d2ec1 (patch)
treea587905103d9c64297305f82d4a0cc83601e0789
parent19819b1384c655f04a04db61ae15c1419002e95f (diff)
build FIXME No libc.a for pre-qualified onlyqual-10
-rw-r--r--cpukit/libc/search/qsort.c345
-rw-r--r--cpukit/libc/string/flsl.c38
-rw-r--r--cpukit/libc/string/local.h22
-rw-r--r--cpukit/libc/string/memcpy.c105
-rw-r--r--cpukit/libc/string/memset.c96
-rw-r--r--cpukit/libc/string/strchr.c116
-rw-r--r--cpukit/libc/string/strcmp.c99
-rw-r--r--cpukit/libc/string/strlen.c82
-rw-r--r--cpukit/libc/string/strrchr.c52
-rw-r--r--cpukit/score/cpu/sparc/setjmp.S144
-rw-r--r--spec/build/bsps/bspopts.yml2
-rw-r--r--spec/build/bsps/optldflags.yml3
-rw-r--r--spec/build/bsps/optldflagsqualonly.yml24
-rw-r--r--spec/build/cpukit/cpusparcqualonly.yml17
-rw-r--r--spec/build/cpukit/librtemscpu.yml4
-rw-r--r--spec/build/cpukit/objqualonly.yml22
16 files changed, 1170 insertions, 1 deletions
diff --git a/cpukit/libc/search/qsort.c b/cpukit/libc/search/qsort.c
new file mode 100644
index 0000000000..b53400aa8e
--- /dev/null
+++ b/cpukit/libc/search/qsort.c
@@ -0,0 +1,345 @@
+/*
+FUNCTION
+<<qsort>>---sort an array
+
+INDEX
+ qsort
+
+SYNOPSIS
+ #include <stdlib.h>
+ void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
+ int (*<[compar]>)(const void *, const void *) );
+
+DESCRIPTION
+<<qsort>> sorts an array (beginning at <[base]>) of <[nmemb]> objects.
+<[size]> describes the size of each element of the array.
+
+You must supply a pointer to a comparison function, using the argument
+shown as <[compar]>. (This permits sorting objects of unknown
+properties.) Define the comparison function to accept two arguments,
+each a pointer to an element of the array starting at <[base]>. The
+result of <<(*<[compar]>)>> must be negative if the first argument is
+less than the second, zero if the two arguments match, and positive if
+the first argument is greater than the second (where ``less than'' and
+``greater than'' refer to whatever arbitrary ordering is appropriate).
+
+The array is sorted in place; that is, when <<qsort>> returns, the
+array elements beginning at <[base]> have been reordered.
+
+RETURNS
+<<qsort>> does not return a result.
+
+PORTABILITY
+<<qsort>> is required by ANSI (without specifying the sorting algorithm).
+*/
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+#include <_ansi.h>
+#include <sys/cdefs.h>
+#include <stdlib.h>
+
+#ifndef __GNUC__
+#define inline
+#endif
+
+#if defined(I_AM_QSORT_R)
+typedef int cmp_t(void *, const void *, const void *);
+#elif defined(I_AM_GNU_QSORT_R)
+typedef int cmp_t(const void *, const void *, void *);
+#else
+typedef int cmp_t(const void *, const void *);
+#endif
+static inline char *med3 (char *, char *, char *, cmp_t *, void *);
+static inline void swapfunc (char *, char *, int, int);
+
+#define min(a, b) (a) < (b) ? a : b
+
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+#define swapcode(TYPE, parmi, parmj, n) { \
+ long i = (n) / sizeof (TYPE); \
+ TYPE *pi = (TYPE *) (parmi); \
+ TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+
+static inline void
+swapfunc (char *a,
+ char *b,
+ int n,
+ int swaptype)
+{
+ if(swaptype <= 1)
+ swapcode(long, a, b, n)
+ else
+ swapcode(char, a, b, n)
+}
+
+#define swap(a, b) \
+ if (swaptype == 0) { \
+ long t = *(long *)(a); \
+ *(long *)(a) = *(long *)(b); \
+ *(long *)(b) = t; \
+ } else \
+ swapfunc(a, b, es, swaptype)
+
+#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
+
+#if defined(I_AM_QSORT_R)
+#define CMP(t, x, y) (cmp((t), (x), (y)))
+#elif defined(I_AM_GNU_QSORT_R)
+#define CMP(t, x, y) (cmp((x), (y), (t)))
+#else
+#define CMP(t, x, y) (cmp((x), (y)))
+#endif
+
+static inline char *
+med3 (char *a,
+ char *b,
+ char *c,
+ cmp_t *cmp,
+ void *thunk
+#if !defined(I_AM_QSORT_R) && !defined(I_AM_GNU_QSORT_R)
+__unused
+#endif
+)
+{
+ return CMP(thunk, a, b) < 0 ?
+ (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
+ :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
+}
+
+/*
+ * Classical function call recursion wastes a lot of stack space. Each
+ * recursion level requires a full stack frame comprising all local variables
+ * and additional space as dictated by the processor calling convention.
+ *
+ * This implementation instead stores the variables that are unique for each
+ * recursion level in a parameter stack array, and uses iteration to emulate
+ * recursion. Function call recursion is not used until the array is full.
+ *
+ * To ensure the stack consumption isn't worsened by this design, the size of
+ * the parameter stack array is chosen to be similar to the stack frame
+ * excluding the array. Each function call recursion level can handle this
+ * number of iterative recursion levels.
+ */
+#define PARAMETER_STACK_LEVELS 8u
+
+#if defined(I_AM_QSORT_R)
+void
+__bsd_qsort_r (void *a,
+ size_t n,
+ size_t es,
+ void *thunk,
+ cmp_t *cmp)
+#elif defined(I_AM_GNU_QSORT_R)
+void
+qsort_r (void *a,
+ size_t n,
+ size_t es,
+ cmp_t *cmp,
+ void *thunk)
+#else
+#define thunk NULL
+void
+qsort (void *a,
+ size_t n,
+ size_t es,
+ cmp_t *cmp)
+#endif
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ size_t d, r;
+ int cmp_result;
+ int swaptype, swap_cnt;
+ size_t recursion_level = 0;
+ struct { void *a; size_t n; } parameter_stack[PARAMETER_STACK_LEVELS];
+
+ SWAPINIT(a, es);
+loop: swap_cnt = 0;
+ if (n < 7) {
+ /* Short arrays are insertion sorted. */
+ for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
+ for (pl = pm; pl > (char *) a && CMP(thunk, pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ goto pop;
+ }
+
+ /* Select a pivot element, move it to the left. */
+ pm = (char *) a + (n / 2) * es;
+ if (n > 7) {
+ pl = a;
+ pn = (char *) a + (n - 1) * es;
+ if (n > 40) {
+ d = (n / 8) * es;
+ pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
+ pm = med3(pm - d, pm, pm + d, cmp, thunk);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
+ }
+ pm = med3(pl, pm, pn, cmp, thunk);
+ }
+ swap(a, pm);
+
+ /*
+ * Sort the array relative the pivot in four ranges as follows:
+ * { elems == pivot, elems < pivot, elems > pivot, elems == pivot }
+ */
+ pa = pb = (char *) a + es;
+ pc = pd = (char *) a + (n - 1) * es;
+ for (;;) {
+ /* Scan left to right stopping at first element > pivot. */
+ while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) {
+ /* Move elements == pivot to the left (to pa) */
+ if (cmp_result == 0) {
+ swap_cnt = 1;
+ swap(pa, pb);
+ pa += es;
+ }
+ pb += es;
+ }
+ /* Scan right to left stopping at first element < pivot. */
+ while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) {
+ /* Move elements == pivot to the right (to pd) */
+ if (cmp_result == 0) {
+ swap_cnt = 1;
+ swap(pc, pd);
+ pd -= es;
+ }
+ pc -= es;
+ }
+ if (pb > pc)
+ break;
+ /* The scan has found two elements to swap with each other. */
+ swap(pb, pc);
+ swap_cnt = 1;
+ pb += es;
+ pc -= es;
+ }
+ if (swap_cnt == 0) { /* Switch to insertion sort */
+ for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
+ for (pl = pm; pl > (char *) a && CMP(thunk, pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ goto pop;
+ }
+
+ /*
+ * Rearrange the array in three parts sorted like this:
+ * { elements < pivot, elements == pivot, elements > pivot }
+ */
+ pn = (char *) a + n * es;
+ r = min(pa - (char *)a, pb - pa);
+ vecswap(a, pb - r, r);
+ r = min(pd - pc, pn - pd - es);
+ vecswap(pb, pn - r, r);
+ d = pb - pa; /* d = Size of left part. */
+ r = pd - pc; /* r = Size of right part. */
+ pn -= r; /* pn = Base of right part. */
+
+ /*
+ * Check which of the left and right parts are larger.
+ * Set (a, n) to (base, size) of the larger part.
+ * Set (pa, r) to (base, size) of the smaller part.
+ */
+ if (r > d) { /* Right part is the larger part */
+ pa = a;
+ a = pn;
+ n = r;
+ r = d;
+ }
+ else { /* Left part is the larger part, or both are equal. */
+ pa = pn;
+ n = d;
+ }
+
+ /*
+ * The left and right parts each need further sorting if they
+ * contain two elements or more. If both need sorting we use
+ * recursion to sort the smaller part and save the larger part
+ * to be sorted by iteration after the recursion.
+ * Using recursion only for the smaller part guarantees a
+ * recursion depth that is bounded to be less than (log2(n)).
+ */
+ if (r > es) { /* Smaller part > 1 element. Both parts need sorting. */
+ if (recursion_level < PARAMETER_STACK_LEVELS) {
+ /*
+ * The smaller part needs to be recursively sorted
+ * before the larger part is sorted. To avoid function
+ * call recursion the parameters for the larger part
+ * are pushed on the parameter_stack array. The smaller
+ * part is sorted using iteration and the larger part
+ * will be sorted when the parameter_stack is popped
+ * after the smaller part has been sorted.
+ */
+ parameter_stack[recursion_level].a = a;
+ parameter_stack[recursion_level].n = n / es;
+ recursion_level++;
+ a = pa;
+ n = r / es;
+ goto loop;
+ }
+ else {
+ /*
+ * The parameter_stack array is full. The smaller part
+ * is sorted using function call recursion. The larger
+ * part will be sorted after the function call returns.
+ */
+#if defined(I_AM_QSORT_R)
+ __bsd_qsort_r(pa, r / es, es, thunk, cmp);
+#elif defined(I_AM_GNU_QSORT_R)
+ qsort_r(pa, r / es, es, cmp, thunk);
+#else
+ qsort(pa, r / es, es, cmp);
+#endif
+ }
+ }
+ if (n > es) { /* The larger part needs sorting. Iterate to sort. */
+ n = n / es;
+ goto loop;
+ }
+ /* Both left and right parts are one element or less - level done. */
+pop:
+ if (recursion_level != 0) {
+ recursion_level--;
+ a = parameter_stack[recursion_level].a;
+ n = parameter_stack[recursion_level].n;
+ goto loop;
+ }
+}
diff --git a/cpukit/libc/string/flsl.c b/cpukit/libc/string/flsl.c
new file mode 100644
index 0000000000..af6277d1a4
--- /dev/null
+++ b/cpukit/libc/string/flsl.c
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2017 embedded brains GmbH
+ * 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 AUTHOR 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 AUTHOR 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.
+ */
+
+#include <strings.h>
+#include <limits.h>
+
+int
+flsl(long i)
+{
+
+ if (i == 0)
+ return 0;
+
+ return (sizeof(i) * CHAR_BIT - __builtin_clzl(i));
+}
diff --git a/cpukit/libc/string/local.h b/cpukit/libc/string/local.h
new file mode 100644
index 0000000000..ef7ba3918f
--- /dev/null
+++ b/cpukit/libc/string/local.h
@@ -0,0 +1,22 @@
+#include <_ansi.h>
+#ifndef __rtems__
+#include <../ctype/local.h>
+#endif /* __rtems__ */
+
+/* internal function to compute width of wide char. */
+int __wcwidth (wint_t);
+
+/*
+ Taken from glibc:
+ Add the compiler optimization to inhibit loop transformation to library
+ calls. This is used to avoid recursive calls in memset and memmove
+ default implementations.
+*/
+#ifdef _HAVE_CC_INHIBIT_LOOP_TO_LIBCALL
+# define __inhibit_loop_to_libcall \
+ __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns")))
+#else
+# define __inhibit_loop_to_libcall
+#endif
+
+
diff --git a/cpukit/libc/string/memcpy.c b/cpukit/libc/string/memcpy.c
new file mode 100644
index 0000000000..52f716b927
--- /dev/null
+++ b/cpukit/libc/string/memcpy.c
@@ -0,0 +1,105 @@
+/*
+FUNCTION
+ <<memcpy>>---copy memory regions
+
+SYNOPSIS
+ #include <string.h>
+ void* memcpy(void *restrict <[out]>, const void *restrict <[in]>,
+ size_t <[n]>);
+
+DESCRIPTION
+ This function copies <[n]> bytes from the memory region
+ pointed to by <[in]> to the memory region pointed to by
+ <[out]>.
+
+ If the regions overlap, the behavior is undefined.
+
+RETURNS
+ <<memcpy>> returns a pointer to the first byte of the <[out]>
+ region.
+
+PORTABILITY
+<<memcpy>> is ANSI C.
+
+<<memcpy>> requires no supporting OS subroutines.
+
+QUICKREF
+ memcpy ansi pure
+ */
+
+#include <_ansi.h>
+#include <string.h>
+#include "local.h"
+
+/* Nonzero if either X or Y is not aligned on a "long" boundary. */
+#define UNALIGNED(X, Y) \
+ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+
+/* How many bytes are copied each iteration of the 4X unrolled loop. */
+#define BIGBLOCKSIZE (sizeof (long) << 2)
+
+/* How many bytes are copied each iteration of the word copy loop. */
+#define LITTLEBLOCKSIZE (sizeof (long))
+
+/* Threshhold for punting to the byte copier. */
+#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE)
+
+void *
+__inhibit_loop_to_libcall
+memcpy (void *__restrict dst0,
+ const void *__restrict src0,
+ size_t len0)
+{
+#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
+ char *dst = (char *) dst0;
+ char *src = (char *) src0;
+
+ void *save = dst0;
+
+ while (len0--)
+ {
+ *dst++ = *src++;
+ }
+
+ return save;
+#else
+ char *dst = dst0;
+ const char *src = src0;
+ long *aligned_dst;
+ const long *aligned_src;
+
+ /* If the size is small, or either SRC or DST is unaligned,
+ then punt into the byte copy loop. This should be rare. */
+ if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
+ {
+ aligned_dst = (long*)dst;
+ aligned_src = (long*)src;
+
+ /* Copy 4X long words at a time if possible. */
+ while (len0 >= BIGBLOCKSIZE)
+ {
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ len0 -= BIGBLOCKSIZE;
+ }
+
+ /* Copy one long word at a time if possible. */
+ while (len0 >= LITTLEBLOCKSIZE)
+ {
+ *aligned_dst++ = *aligned_src++;
+ len0 -= LITTLEBLOCKSIZE;
+ }
+
+ /* Pick up any residual with a byte copier. */
+ dst = (char*)aligned_dst;
+ src = (char*)aligned_src;
+ }
+
+ while (len0--)
+ *dst++ = *src++;
+
+ return dst0;
+#endif /* not PREFER_SIZE_OVER_SPEED */
+}
diff --git a/cpukit/libc/string/memset.c b/cpukit/libc/string/memset.c
new file mode 100644
index 0000000000..e8e667a241
--- /dev/null
+++ b/cpukit/libc/string/memset.c
@@ -0,0 +1,96 @@
+/*
+FUNCTION
+ <<memset>>---set an area of memory
+
+INDEX
+ memset
+
+SYNOPSIS
+ #include <string.h>
+ void *memset(void *<[dst]>, int <[c]>, size_t <[length]>);
+
+DESCRIPTION
+ This function converts the argument <[c]> into an unsigned
+ char and fills the first <[length]> characters of the array
+ pointed to by <[dst]> to the value.
+
+RETURNS
+ <<memset>> returns the value of <[dst]>.
+
+PORTABILITY
+<<memset>> is ANSI C.
+
+ <<memset>> requires no supporting OS subroutines.
+
+QUICKREF
+ memset ansi pure
+*/
+
+#include <string.h>
+#include "local.h"
+
+#define LBLOCKSIZE (sizeof(long))
+#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
+#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
+
+void *
+__inhibit_loop_to_libcall
+memset (void *m,
+ int c,
+ size_t n)
+{
+ char *s = (char *) m;
+
+#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
+ unsigned int i;
+ unsigned long buffer;
+ unsigned long *aligned_addr;
+ unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an
+ unsigned variable. */
+
+ while (UNALIGNED (s))
+ {
+ if (n--)
+ *s++ = (char) c;
+ else
+ return m;
+ }
+
+ if (!TOO_SMALL (n))
+ {
+ /* If we get this far, we know that n is large and s is word-aligned. */
+ aligned_addr = (unsigned long *) s;
+
+ /* Store D into each char sized location in BUFFER so that
+ we can set large blocks quickly. */
+ buffer = (d << 8) | d;
+ buffer |= (buffer << 16);
+ for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)
+ buffer = (buffer << i) | buffer;
+
+ /* Unroll the loop. */
+ while (n >= LBLOCKSIZE*4)
+ {
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ n -= 4*LBLOCKSIZE;
+ }
+
+ while (n >= LBLOCKSIZE)
+ {
+ *aligned_addr++ = buffer;
+ n -= LBLOCKSIZE;
+ }
+ /* Pick up the remainder with a bytewise loop. */
+ s = (char*)aligned_addr;
+ }
+
+#endif /* not PREFER_SIZE_OVER_SPEED */
+
+ while (n--)
+ *s++ = (char) c;
+
+ return m;
+}
diff --git a/cpukit/libc/string/strchr.c b/cpukit/libc/string/strchr.c
new file mode 100644
index 0000000000..96f30be044
--- /dev/null
+++ b/cpukit/libc/string/strchr.c
@@ -0,0 +1,116 @@
+/*
+FUNCTION
+ <<strchr>>---search for character in string
+
+INDEX
+ strchr
+
+SYNOPSIS
+ #include <string.h>
+ char * strchr(const char *<[string]>, int <[c]>);
+
+DESCRIPTION
+ This function finds the first occurence of <[c]> (converted to
+ a char) in the string pointed to by <[string]> (including the
+ terminating null character).
+
+RETURNS
+ Returns a pointer to the located character, or a null pointer
+ if <[c]> does not occur in <[string]>.
+
+PORTABILITY
+<<strchr>> is ANSI C.
+
+<<strchr>> requires no supporting OS subroutines.
+
+QUICKREF
+ strchr ansi pure
+*/
+
+#include <string.h>
+#include <limits.h>
+
+/* Nonzero if X is not aligned on a "long" boundary. */
+#define UNALIGNED(X) ((long)X & (sizeof (long) - 1))
+
+/* How many bytes are loaded each iteration of the word copy loop. */
+#define LBLOCKSIZE (sizeof (long))
+
+#if LONG_MAX == 2147483647L
+#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
+#else
+#if LONG_MAX == 9223372036854775807L
+/* Nonzero if X (a long int) contains a NULL byte. */
+#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
+#else
+#error long int is not a 32bit or 64bit type.
+#endif
+#endif
+
+/* DETECTCHAR returns nonzero if (long)X contains the byte used
+ to fill (long)MASK. */
+#define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK))
+
+char *
+strchr (const char *s1,
+ int i)
+{
+ const unsigned char *s = (const unsigned char *)s1;
+ unsigned char c = i;
+
+#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
+ unsigned long mask,j;
+ unsigned long *aligned_addr;
+
+ /* Special case for finding 0. */
+ if (!c)
+ {
+ while (UNALIGNED (s))
+ {
+ if (!*s)
+ return (char *) s;
+ s++;
+ }
+ /* Operate a word at a time. */
+ aligned_addr = (unsigned long *) s;
+ while (!DETECTNULL (*aligned_addr))
+ aligned_addr++;
+ /* Found the end of string. */
+ s = (const unsigned char *) aligned_addr;
+ while (*s)
+ s++;
+ return (char *) s;
+ }
+
+ /* All other bytes. Align the pointer, then search a long at a time. */
+ while (UNALIGNED (s))
+ {
+ if (!*s)
+ return NULL;
+ if (*s == c)
+ return (char *) s;
+ s++;
+ }
+
+ mask = c;
+ for (j = 8; j < LBLOCKSIZE * 8; j <<= 1)
+ mask = (mask << j) | mask;
+
+ aligned_addr = (unsigned long *) s;
+ while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask))
+ aligned_addr++;
+
+ /* The block of bytes currently pointed to by aligned_addr
+ contains either a null or the target char, or both. We
+ catch it using the bytewise search. */
+
+ s = (unsigned char *) aligned_addr;
+
+#endif /* not PREFER_SIZE_OVER_SPEED */
+
+ while (*s && *s != c)
+ s++;
+ if (*s == c)
+ return (char *)s;
+ return NULL;
+}
diff --git a/cpukit/libc/string/strcmp.c b/cpukit/libc/string/strcmp.c
new file mode 100644
index 0000000000..894424a690
--- /dev/null
+++ b/cpukit/libc/string/strcmp.c
@@ -0,0 +1,99 @@
+/*
+FUNCTION
+ <<strcmp>>---character string compare
+
+INDEX
+ strcmp
+
+SYNOPSIS
+ #include <string.h>
+ int strcmp(const char *<[a]>, const char *<[b]>);
+
+DESCRIPTION
+ <<strcmp>> compares the string at <[a]> to
+ the string at <[b]>.
+
+RETURNS
+ If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>,
+ <<strcmp>> returns a number greater than zero. If the two
+ strings match, <<strcmp>> returns zero. If <<*<[a]>>>
+ sorts lexicographically before <<*<[b]>>>, <<strcmp>> returns a
+ number less than zero.
+
+PORTABILITY
+<<strcmp>> is ANSI C.
+
+<<strcmp>> requires no supporting OS subroutines.
+
+QUICKREF
+ strcmp ansi pure
+*/
+
+#include <string.h>
+#include <limits.h>
+
+/* Nonzero if either X or Y is not aligned on a "long" boundary. */
+#define UNALIGNED(X, Y) \
+ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
+
+/* DETECTNULL returns nonzero if (long)X contains a NULL byte. */
+#if LONG_MAX == 2147483647L
+#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
+#else
+#if LONG_MAX == 9223372036854775807L
+#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
+#else
+#error long int is not a 32bit or 64bit type.
+#endif
+#endif
+
+#ifndef DETECTNULL
+#error long int is not a 32bit or 64bit byte
+#endif
+
+int
+strcmp (const char *s1,
+ const char *s2)
+{
+#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
+ while (*s1 != '\0' && *s1 == *s2)
+ {
+ s1++;
+ s2++;
+ }
+
+ return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+#else
+ unsigned long *a1;
+ unsigned long *a2;
+
+ /* If s1 or s2 are unaligned, then compare bytes. */
+ if (!UNALIGNED (s1, s2))
+ {
+ /* If s1 and s2 are word-aligned, compare them a word at a time. */
+ a1 = (unsigned long*)s1;
+ a2 = (unsigned long*)s2;
+ while (*a1 == *a2)
+ {
+ /* To get here, *a1 == *a2, thus if we find a null in *a1,
+ then the strings must be equal, so return zero. */
+ if (DETECTNULL (*a1))
+ return 0;
+
+ a1++;
+ a2++;
+ }
+
+ /* A difference was detected in last few bytes of s1, so search bytewise */
+ s1 = (char*)a1;
+ s2 = (char*)a2;
+ }
+
+ while (*s1 != '\0' && *s1 == *s2)
+ {
+ s1++;
+ s2++;
+ }
+ return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+#endif /* not PREFER_SIZE_OVER_SPEED */
+}
diff --git a/cpukit/libc/string/strlen.c b/cpukit/libc/string/strlen.c
new file mode 100644
index 0000000000..acffa49e14
--- /dev/null
+++ b/cpukit/libc/string/strlen.c
@@ -0,0 +1,82 @@
+/*
+FUNCTION
+ <<strlen>>---character string length
+
+INDEX
+ strlen
+
+SYNOPSIS
+ #include <string.h>
+ size_t strlen(const char *<[str]>);
+
+DESCRIPTION
+ The <<strlen>> function works out the length of the string
+ starting at <<*<[str]>>> by counting chararacters until it
+ reaches a <<NULL>> character.
+
+RETURNS
+ <<strlen>> returns the character count.
+
+PORTABILITY
+<<strlen>> is ANSI C.
+
+<<strlen>> requires no supporting OS subroutines.
+
+QUICKREF
+ strlen ansi pure
+*/
+
+#include <_ansi.h>
+#include <string.h>
+#include <limits.h>
+
+#define LBLOCKSIZE (sizeof (long))
+#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
+
+#if LONG_MAX == 2147483647L
+#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
+#else
+#if LONG_MAX == 9223372036854775807L
+/* Nonzero if X (a long int) contains a NULL byte. */
+#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
+#else
+#error long int is not a 32bit or 64bit type.
+#endif
+#endif
+
+#ifndef DETECTNULL
+#error long int is not a 32bit or 64bit byte
+#endif
+
+size_t
+strlen (const char *str)
+{
+ const char *start = str;
+
+#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
+ unsigned long *aligned_addr;
+
+ /* Align the pointer, so we can search a word at a time. */
+ while (UNALIGNED (str))
+ {
+ if (!*str)
+ return str - start;
+ str++;
+ }
+
+ /* If the string is word-aligned, we can check for the presence of
+ a null in each word-sized block. */
+ aligned_addr = (unsigned long *)str;
+ while (!DETECTNULL (*aligned_addr))
+ aligned_addr++;
+
+ /* Once a null is detected, we check each byte in that block for a
+ precise position of the null. */
+ str = (char *) aligned_addr;
+
+#endif /* not PREFER_SIZE_OVER_SPEED */
+
+ while (*str)
+ str++;
+ return str - start;
+}
diff --git a/cpukit/libc/string/strrchr.c b/cpukit/libc/string/strrchr.c
new file mode 100644
index 0000000000..04897e162a
--- /dev/null
+++ b/cpukit/libc/string/strrchr.c
@@ -0,0 +1,52 @@
+/*
+FUNCTION
+ <<strrchr>>---reverse search for character in string
+
+INDEX
+ strrchr
+
+SYNOPSIS
+ #include <string.h>
+ char * strrchr(const char *<[string]>, int <[c]>);
+
+DESCRIPTION
+ This function finds the last occurence of <[c]> (converted to
+ a char) in the string pointed to by <[string]> (including the
+ terminating null character).
+
+RETURNS
+ Returns a pointer to the located character, or a null pointer
+ if <[c]> does not occur in <[string]>.
+
+PORTABILITY
+<<strrchr>> is ANSI C.
+
+<<strrchr>> requires no supporting OS subroutines.
+
+QUICKREF
+ strrchr ansi pure
+*/
+
+#include <string.h>
+
+char *
+strrchr (const char *s,
+ int i)
+{
+ const char *last = NULL;
+
+ if (i)
+ {
+ while ((s=strchr(s, i)))
+ {
+ last = s;
+ s++;
+ }
+ }
+ else
+ {
+ last = strchr(s, i);
+ }
+
+ return (char *) last;
+}
diff --git a/cpukit/score/cpu/sparc/setjmp.S b/cpukit/score/cpu/sparc/setjmp.S
new file mode 100644
index 0000000000..613df2ba20
--- /dev/null
+++ b/cpukit/score/cpu/sparc/setjmp.S
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Modified for incorporation into newlib by Joel Sherrill
+ * (joel@OARcorp.com), On-Line Applications Research, 1995.
+ * Did the following:
+ * + merged in DEFS.h
+ * + removed error check since it prevented using this setjmp
+ * to "context switch"
+ * + added the support for the "user label" and "register" prefix
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * from: $Header$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)_setjmp.s 8.1 (Berkeley) 6/4/93"
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/*********************************************************************
+ *********************************************************************
+ * Contents of DEFS.h *
+ *********************************************************************
+ *********************************************************************/
+
+#ifdef PROF
+#define ENTRY(x) \
+ .align 4; .globl SYM(x); .proc 1; SYM(x):; .data; .align 4; 1: .long 0; \
+ .text; save %sp,-96,%sp; sethi %hi(1b),%o0; call mcount; \
+ or %lo(1b),%o0,%o0; restore
+#else
+#define ENTRY(x) \
+ .align 4; .globl SYM(x); .proc 1; SYM(x):
+#endif
+
+
+
+/*********************************************************************
+ *********************************************************************
+ * END of DEFS.h *
+ *********************************************************************
+ *********************************************************************/
+
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ * _longjmp(a,v)
+ * will generate a "return(v?v:1)" from
+ * the last call to
+ * _setjmp(a)
+ * by unwinding the call stack.
+ * The previous signal state is NOT restored.
+ */
+
+
+/* #include "DEFS.h" */
+
+ENTRY(setjmp)
+ENTRY(_setjmp)
+ st %sp, [%o0] /* caller's stack pointer */
+ st %i7, [%o0+4] /* caller's return pc */
+ st %fp, [%o0+8] /* store caller's frame pointer */
+ st %o7, [%o0+12]
+ retl
+ clr %o0 ! return 0
+
+ENTRY(longjmp)
+ENTRY(_longjmp)
+ ta 0x03 /* flush registers */
+ addcc %o1, %g0, %g1 ! compute v ? v : 1 in a global register
+ be,a 0f
+ mov 1, %g1
+0:
+ ld [%o0], %sp /* caller's stack pointer */
+
+ ldd [%sp], %l0
+ ldd [%sp+8], %l2
+ ldd [%sp+16], %l4
+ ldd [%sp+24], %l6
+
+ ldd [%sp+32], %i0
+ ldd [%sp+40], %i2
+ ldd [%sp+48], %i4
+
+ ld [%o0+4], %i7 /* caller's return pc */
+ ld [%o0+8], %fp /* caller's frame pointer */
+ ld [%o0+12], %o7
+
+ jmp %o7 + 8 ! success, return %g1
+ mov %g1, %o0
+
diff --git a/spec/build/bsps/bspopts.yml b/spec/build/bsps/bspopts.yml
index 836d94476e..c7dd884012 100644
--- a/spec/build/bsps/bspopts.yml
+++ b/spec/build/bsps/bspopts.yml
@@ -20,6 +20,8 @@ links:
- role: build-dependency
uid: optldflags
- role: build-dependency
+ uid: optldflagsqualonly
+- role: build-dependency
uid: optldflagsbsp
- role: build-dependency
uid: optmakelegacy
diff --git a/spec/build/bsps/optldflags.yml b/spec/build/bsps/optldflags.yml
index d0e365f407..b82600d809 100644
--- a/spec/build/bsps/optldflags.yml
+++ b/spec/build/bsps/optldflags.yml
@@ -12,7 +12,8 @@ default:
default-by-variant: []
description: |
Flags passed to the linker (GNU ld)
-enabled-by: true
+enabled-by:
+ not: RTEMS_QUAL_ONLY
links: []
name: LDFLAGS
type: build
diff --git a/spec/build/bsps/optldflagsqualonly.yml b/spec/build/bsps/optldflagsqualonly.yml
new file mode 100644
index 0000000000..50ca7e52f3
--- /dev/null
+++ b/spec/build/bsps/optldflagsqualonly.yml
@@ -0,0 +1,24 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+- get-string: null
+- split: null
+- env-append: null
+- env-append: PKGCONFIG_LDFLAGS
+build-type: option
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+default:
+- -Wl,--gc-sections
+- -nodefaultlibs
+- -Wl,--start-group
+- -lrtemscpu
+- -lrtemsbsp
+- -lgcc
+- -Wl,--end-group
+default-by-variant: []
+description: |
+ Flags passed to the linker (GNU ld)
+enabled-by: RTEMS_QUAL_ONLY
+links: []
+name: LDFLAGS
+type: build
diff --git a/spec/build/cpukit/cpusparcqualonly.yml b/spec/build/cpukit/cpusparcqualonly.yml
new file mode 100644
index 0000000000..1aede8582b
--- /dev/null
+++ b/spec/build/cpukit/cpusparcqualonly.yml
@@ -0,0 +1,17 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+build-type: objects
+cflags: []
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+cppflags: []
+cxxflags: []
+enabled-by:
+ and:
+ - sparc
+ - RTEMS_QUAL_ONLY
+includes: []
+install: []
+links: []
+source:
+- cpukit/score/cpu/sparc/setjmp.S
+type: build
diff --git a/spec/build/cpukit/librtemscpu.yml b/spec/build/cpukit/librtemscpu.yml
index 46f65fcd27..64dbdeb11f 100644
--- a/spec/build/cpukit/librtemscpu.yml
+++ b/spec/build/cpukit/librtemscpu.yml
@@ -247,10 +247,14 @@ links:
- role: build-dependency
uid: cpusparcqual
- role: build-dependency
+ uid: cpusparcqualonly
+- role: build-dependency
uid: grprtemscpunoqual
- role: build-dependency
uid: librtemscpuextra
- role: build-dependency
+ uid: objqualonly
+- role: build-dependency
uid: objsmpqual
- role: build-dependency
uid: vckey
diff --git a/spec/build/cpukit/objqualonly.yml b/spec/build/cpukit/objqualonly.yml
new file mode 100644
index 0000000000..d36fc63865
--- /dev/null
+++ b/spec/build/cpukit/objqualonly.yml
@@ -0,0 +1,22 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+build-type: objects
+cflags: []
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+cppflags: []
+cxxflags: []
+enabled-by:
+- RTEMS_QUAL_ONLY
+includes: []
+install: []
+links: []
+source:
+- cpukit/libc/search/qsort.c
+- cpukit/libc/string/flsl.c
+- cpukit/libc/string/memcpy.c
+- cpukit/libc/string/memset.c
+- cpukit/libc/string/strcmp.c
+- cpukit/libc/string/strlen.c
+- cpukit/libc/string/strchr.c
+- cpukit/libc/string/strrchr.c
+type: build