summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--c/src/tests/libffi/Makefile.am13
-rw-r--r--c/src/tests/libffi/configure.in46
-rw-r--r--c/src/tests/libffi/ffitest/Makefile.am43
-rw-r--r--c/src/tests/libffi/ffitest/ffitest.c735
-rw-r--r--c/src/tests/libffi/ffitest/init.c35
-rw-r--r--c/src/tests/libffi/ffitest/system.h36
-rw-r--r--c/src/tests/libffi/libffi.am11
-rw-r--r--c/src/tests/sptests/threaditerate/Makefile.am43
-rw-r--r--c/src/tests/sptests/threaditerate/init.c202
-rw-r--r--c/src/tests/sptests/threaditerate/itrontask.c52
-rw-r--r--c/src/tests/sptests/threaditerate/pthread.c46
-rw-r--r--c/src/tests/sptests/threaditerate/rtemstask.c47
-rw-r--r--c/src/tests/sptests/threaditerate/system.h98
-rw-r--r--c/src/tests/sptests/threaditerate/threadinfo.c178
-rw-r--r--c/src/tests/sptests/threaditerate/threaditerate.scn205
-rw-r--r--make/custom/mbx821_001.cfg12
-rw-r--r--make/custom/mbx860_002.cfg12
-rw-r--r--make/custom/mbx8xx.cfg196
18 files changed, 2010 insertions, 0 deletions
diff --git a/c/src/tests/libffi/Makefile.am b/c/src/tests/libffi/Makefile.am
new file mode 100644
index 0000000000..9710c7d2dd
--- /dev/null
+++ b/c/src/tests/libffi/Makefile.am
@@ -0,0 +1,13 @@
+##
+## $Id$
+##
+
+AUTOMAKE_OPTIONS = foreign 1.4
+ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal
+
+SUBDIRS = ffitest
+
+EXTRA_DIST = libffi.am
+
+include $(top_srcdir)/../../../../automake/subdirs.am
+include $(top_srcdir)/../../../../automake/local.am
diff --git a/c/src/tests/libffi/configure.in b/c/src/tests/libffi/configure.in
new file mode 100644
index 0000000000..760a4bd771
--- /dev/null
+++ b/c/src/tests/libffi/configure.in
@@ -0,0 +1,46 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl
+dnl $Id$
+
+AC_PREREQ(2.13)
+AC_INIT(ffitest)
+RTEMS_TOP(../../../..)
+AC_CONFIG_AUX_DIR(../../../..)
+
+RTEMS_CANONICAL_TARGET_CPU
+
+AM_INIT_AUTOMAKE(rtems-c-src-tests-libffi,$RTEMS_VERSION,no)
+AM_MAINTAINER_MODE
+
+RTEMS_ENABLE_INLINES
+RTEMS_ENABLE_CXX
+RTEMS_ENABLE_GCC28
+RTEMS_ENABLE_BARE
+
+RTEMS_ENV_RTEMSBSP
+RTEMS_CHECK_CPU
+RTEMS_CANONICAL_HOST
+
+RTEMS_PROJECT_ROOT
+
+RTEMS_PROG_CC_FOR_TARGET
+
+if test "$RTEMS_HAS_CPLUSPLUS" = "yes"; then
+ RTEMS_PROG_CXX_FOR_TARGET
+fi
+
+RTEMS_CANONICALIZE_TOOLS
+
+RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP)
+RTEMS_CHECK_CXX(RTEMS_BSP)
+
+AC_SUBST(BARE_CPU_CFLAGS)
+AC_SUBST(BARE_CPU_MODEL)
+
+AM_CONDITIONAL(HAS_CXX,test "$HAS_CPLUSPLUS" = "yes")
+
+# Explicitly list all Makefiles here
+AC_OUTPUT(
+Makefile
+ffitest/Makefile
+)
diff --git a/c/src/tests/libffi/ffitest/Makefile.am b/c/src/tests/libffi/ffitest/Makefile.am
new file mode 100644
index 0000000000..8ea12d706e
--- /dev/null
+++ b/c/src/tests/libffi/ffitest/Makefile.am
@@ -0,0 +1,43 @@
+##
+## $Id$
+##
+
+AUTOMAKE_OPTIONS = foreign 1.4
+TEST = ffitest
+
+MANAGERS = io
+
+C_FILES = init.c ffitest.c
+C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o)
+
+H_FILES = system.h
+noinst_HEADERS = $(H_FILES)
+
+DOCTYPES = scn
+DOCS = $(DOCTYPES:%=$(TEST).%)
+
+SRCS = $(DOCS) $(C_FILES) $(H_FILES)
+OBJS = $(C_O_FILES)
+
+PRINT_SRCS = $(DOCS)
+
+PGM = ${ARCH}/$(TEST).exe
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+include $(top_srcdir)/libffi.am
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+LD_LIBS += -lffi
+
+${PGM}: $(OBJS) $(LINK_FILES)
+ $(make-exe)
+
+all: ${ARCH} $(TMPINSTALL_FILES)
+
+EXTRA_DIST = $(C_FILES) $(DOCS)
+
+include $(top_srcdir)/../../../../automake/local.am
diff --git a/c/src/tests/libffi/ffitest/ffitest.c b/c/src/tests/libffi/ffitest/ffitest.c
new file mode 100644
index 0000000000..abc09a97b7
--- /dev/null
+++ b/c/src/tests/libffi/ffitest/ffitest.c
@@ -0,0 +1,735 @@
+/* -----------------------------------------------------------------------
+ ffitest.c - Copyright (c) 1996, 1997, 1998 Cygnus Solutions
+
+ $Id$
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ ``Software''), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+ ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+#include <rtems.h>
+#include <rtems/error.h>
+
+/* This is lame. Long double support is barely there under SunOS 4.x */
+#if defined(SPARC) && (SIZEOF_LONG_DOUBLE != 16)
+#define BROKEN_LONG_DOUBLE
+#endif
+
+#define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0
+
+static int fail(char *file, int line)
+{
+ fprintf(stderr, "Test failure: %s line %d\n", file, line);
+ exit(EXIT_FAILURE);
+ /*@notreached@*/
+ return 0;
+}
+
+#define MAX_ARGS 256
+
+static size_t my_strlen(char *s)
+{
+ return (strlen(s));
+}
+
+static int promotion(signed char sc, signed short ss,
+ unsigned char uc, unsigned short us)
+{
+ int r = (int) sc + (int) ss + (int) uc + (int) us;
+
+ return r;
+}
+
+static signed char return_sc(signed char sc)
+{
+ return sc;
+}
+
+static unsigned char return_uc(unsigned char uc)
+{
+ return uc;
+}
+
+static long long return_ll(long long ll)
+{
+ return ll;
+}
+
+static int floating(int a, float b, double c, long double d, int e)
+{
+ int i;
+
+#if 0
+ /* This is ifdef'd out for now. long double support under SunOS/gcc
+ is pretty much non-existent. You'll get the odd bus error in library
+ routines like printf(). */
+ printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e);
+#endif
+
+ i = (int) ((float)a/b + ((float)c/(float)d));
+
+ return i;
+}
+
+static float many(float f1,
+ float f2,
+ float f3,
+ float f4,
+ float f5,
+ float f6,
+ float f7,
+ float f8,
+ float f9,
+ float f10,
+ float f11,
+ float f12,
+ float f13)
+{
+#if 0
+ printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
+ (double) f1, (double) f2, (double) f3, (double) f4, (double) f5,
+ (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
+ (double) f11, (double) f12, (double) f13);
+#endif
+
+ return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+static double dblit(float f)
+{
+ return f/3.0;
+}
+
+static long double ldblit(float f)
+{
+ return (long double) (((long double) f)/ (long double) 3.0);
+}
+
+typedef struct
+{
+ unsigned char uc;
+ double d;
+ unsigned int ui;
+} test_structure_1;
+
+typedef struct
+{
+ double d1;
+ double d2;
+} test_structure_2;
+
+typedef struct
+{
+ int si;
+} test_structure_3;
+
+typedef struct
+{
+ unsigned ui1;
+ unsigned ui2;
+ unsigned ui3;
+} test_structure_4;
+
+typedef struct
+{
+ char c1;
+ char c2;
+} test_structure_5;
+
+static test_structure_1 struct1(test_structure_1 ts)
+{
+ /*@-type@*/
+ ts.uc++;
+ /*@=type@*/
+ ts.d--;
+ ts.ui++;
+
+ return ts;
+}
+
+static test_structure_2 struct2(test_structure_2 ts)
+{
+ ts.d1--;
+ ts.d2--;
+
+ return ts;
+}
+
+static test_structure_3 struct3(test_structure_3 ts)
+{
+ ts.si = -(ts.si*2);
+
+ return ts;
+}
+
+static test_structure_4 struct4(test_structure_4 ts)
+{
+ ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
+
+ return ts;
+}
+
+static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
+{
+ ts1.c1 += ts2.c1;
+ ts1.c2 -= ts2.c2;
+
+ return ts1;
+}
+
+/* Take an int and a float argument, together with int userdata, and */
+/* return the sum. */
+static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
+{
+ *(int*)resp =
+ *(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
+}
+
+typedef int (*closure_test_type)(int, float);
+
+int ffi_main( void )
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ char *s;
+ signed char sc;
+ unsigned char uc;
+ signed short ss;
+ unsigned short us;
+ unsigned long ul;
+ long long ll;
+ float f;
+ double d;
+ long double ld;
+ signed int si1;
+ signed int si2;
+
+#if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
+ long long rint;
+#else
+ int rint;
+#endif
+ long long rlonglong;
+
+ ffi_type ts1_type;
+ ffi_type ts2_type;
+ ffi_type ts3_type;
+ ffi_type ts4_type;
+ ffi_type ts5_type;
+ ffi_type *ts1_type_elements[4];
+ ffi_type *ts2_type_elements[3];
+ ffi_type *ts3_type_elements[2];
+ ffi_type *ts4_type_elements[4];
+ ffi_type *ts5_type_elements[3];
+
+ ts1_type.size = 0;
+ ts1_type.alignment = 0;
+ ts1_type.type = FFI_TYPE_STRUCT;
+
+ ts2_type.size = 0;
+ ts2_type.alignment = 0;
+ ts2_type.type = FFI_TYPE_STRUCT;
+
+ ts3_type.size = 0;
+ ts3_type.alignment = 0;
+ ts3_type.type = FFI_TYPE_STRUCT;
+
+ ts4_type.size = 0;
+ ts4_type.alignment = 0;
+ ts4_type.type = FFI_TYPE_STRUCT;
+
+ ts5_type.size = 0;
+ ts5_type.alignment = 0;
+ ts5_type.type = FFI_TYPE_STRUCT;
+
+ /*@-immediatetrans@*/
+ ts1_type.elements = ts1_type_elements;
+ ts2_type.elements = ts2_type_elements;
+ ts3_type.elements = ts3_type_elements;
+ ts4_type.elements = ts4_type_elements;
+ ts5_type.elements = ts5_type_elements;
+ /*@=immediatetrans@*/
+
+ ts1_type_elements[0] = &ffi_type_uchar;
+ ts1_type_elements[1] = &ffi_type_double;
+ ts1_type_elements[2] = &ffi_type_uint;
+ ts1_type_elements[3] = NULL;
+
+ ts2_type_elements[0] = &ffi_type_double;
+ ts2_type_elements[1] = &ffi_type_double;
+ ts2_type_elements[2] = NULL;
+
+ ts3_type_elements[0] = &ffi_type_sint;
+ ts3_type_elements[1] = NULL;
+
+ ts4_type_elements[0] = &ffi_type_uint;
+ ts4_type_elements[1] = &ffi_type_uint;
+ ts4_type_elements[2] = &ffi_type_uint;
+ ts4_type_elements[3] = NULL;
+
+ ts5_type_elements[0] = &ffi_type_schar;
+ ts5_type_elements[1] = &ffi_type_schar;
+ ts5_type_elements[2] = NULL;
+
+ ul = 0;
+
+ /* return value tests */
+ {
+#if defined(MIPS) /* || defined(ARM) */
+ puts ("long long tests not run. This is a known bug on this architecture.");
+#else
+ args[0] = &ffi_type_sint64;
+ values[0] = &ll;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_sint64, args) == FFI_OK);
+
+ for (ll = 0LL; ll < 100LL; ll++)
+ {
+ ul++;
+ ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+ CHECK(rlonglong == ll);
+ }
+
+ for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
+ {
+ ul++;
+ ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+ CHECK(rlonglong == ll);
+ }
+#endif
+
+ args[0] = &ffi_type_schar;
+ values[0] = &sc;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_schar, args) == FFI_OK);
+
+ for (sc = (signed char) -127;
+ sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
+ {
+ ul++;
+ ffi_call(&cif, FFI_FN(return_sc), &rint, values);
+ CHECK(rint == (int) sc);
+ }
+
+ args[0] = &ffi_type_uchar;
+ values[0] = &uc;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_uchar, args) == FFI_OK);
+
+ for (uc = (unsigned char) '\x00';
+ uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
+ {
+ ul++;
+ ffi_call(&cif, FFI_FN(return_uc), &rint, values);
+ CHECK(rint == (signed int) uc);
+ }
+
+ printf("%lu return value tests run\n", ul);
+ }
+
+#ifdef BROKEN_LONG_DOUBLE
+ printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
+#else
+ /* float arg tests */
+ {
+ args[0] = &ffi_type_float;
+ values[0] = &f;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_longdouble, args) == FFI_OK);
+
+ f = 3.14159;
+
+#if 0
+ /* This is ifdef'd out for now. long double support under SunOS/gcc
+ is pretty much non-existent. You'll get the odd bus error in library
+ routines like printf(). */
+ printf ("%Lf\n", ldblit(f));
+#endif
+ ld = 666;
+ ffi_call(&cif, FFI_FN(ldblit), &ld, values);
+
+#if 0
+ /* This is ifdef'd out for now. long double support under SunOS/gcc
+ is pretty much non-existent. You'll get the odd bus error in library
+ routines like printf(). */
+ printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
+#endif
+
+ /* These are not always the same!! Check for a reasonable delta */
+ /*@-realcompare@*/
+ if (ld - ldblit(f) < LDBL_EPSILON)
+ /*@=realcompare@*/
+ puts("long double return value tests ok!");
+ else
+ CHECK(0);
+ }
+
+ /* float arg tests */
+ {
+ args[0] = &ffi_type_sint;
+ values[0] = &si1;
+ args[1] = &ffi_type_float;
+ values[1] = &f;
+ args[2] = &ffi_type_double;
+ values[2] = &d;
+ args[3] = &ffi_type_longdouble;
+ values[3] = &ld;
+ args[4] = &ffi_type_sint;
+ values[4] = &si2;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
+ &ffi_type_sint, args) == FFI_OK);
+
+ si1 = 6;
+ f = 3.14159;
+ d = (double)1.0/(double)3.0;
+ ld = 2.71828182846L;
+ si2 = 10;
+
+ floating (si1, f, d, ld, si2);
+
+ ffi_call(&cif, FFI_FN(floating), &rint, values);
+
+ printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
+
+ CHECK(rint == floating(si1, f, d, ld, si2));
+
+ printf("float arg tests ok!\n");
+ }
+#endif
+
+ /* strlen tests */
+ {
+ args[0] = &ffi_type_pointer;
+ values[0] = (void*) &s;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_sint, args) == FFI_OK);
+
+ s = "a";
+ ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+ CHECK(rint == 1);
+
+ s = "1234567";
+ ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+ CHECK(rint == 7);
+
+ s = "1234567890123456789012345";
+ ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+ CHECK(rint == 25);
+
+ printf("strlen tests passed\n");
+ }
+
+ /* float arg tests */
+ {
+ args[0] = &ffi_type_float;
+ values[0] = &f;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_double, args) == FFI_OK);
+
+ f = 3.14159;
+
+ ffi_call(&cif, FFI_FN(dblit), &d, values);
+
+ /* These are not always the same!! Check for a reasonable delta */
+ /*@-realcompare@*/
+ CHECK(d - dblit(f) < DBL_EPSILON);
+ /*@=realcompare@*/
+
+ printf("double return value tests ok!\n");
+ }
+
+ /* many arg tests */
+ {
+ float ff;
+ float fa[13];
+
+ for (ul = 0; ul < 13; ul++)
+ {
+ args[ul] = &ffi_type_float;
+ values[ul] = &fa[ul];
+ fa[ul] = (float) ul;
+ }
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13,
+ &ffi_type_float, args) == FFI_OK);
+
+ /*@-usedef@*/
+ ff = many(fa[0], fa[1],
+ fa[2], fa[3],
+ fa[4], fa[5],
+ fa[6], fa[7],
+ fa[8], fa[9],
+ fa[10],fa[11],fa[12]);
+ /*@=usedef@*/
+
+ ffi_call(&cif, FFI_FN(many), &f, values);
+
+ /*@-realcompare@*/
+ if (f - ff < FLT_EPSILON)
+ /*@=realcompare@*/
+ printf("many arg tests ok!\n");
+ else
+#ifdef POWERPC
+ printf("many arg tests failed! This is a gcc bug.\n");
+#else
+ CHECK(0);
+#endif
+ }
+
+ /* promotion tests */
+ {
+ args[0] = &ffi_type_schar;
+ args[1] = &ffi_type_sshort;
+ args[2] = &ffi_type_uchar;
+ args[3] = &ffi_type_ushort;
+ values[0] = &sc;
+ values[1] = &ss;
+ values[2] = &uc;
+ values[3] = &us;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+ &ffi_type_sint, args) == FFI_OK);
+
+ us = 0;
+ ul = 0;
+
+ for (sc = (signed char) -127;
+ sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
+ for (ss = -30000; ss <= 30000; ss += 10000)
+ for (uc = (unsigned char) 0;
+ uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
+ for (us = 0; us <= 60000; us += 10000)
+ {
+ ul++;
+ ffi_call(&cif, FFI_FN(promotion), &rint, values);
+ CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
+ }
+ printf("%lu promotion tests run\n", ul);
+ }
+
+ /* struct tests */
+ {
+ test_structure_1 ts1_arg;
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_1 *ts1_result =
+ (test_structure_1 *) malloc (sizeof(test_structure_1));
+ if (! ts1_result )
+ rtems_panic("Could not get memory for struct 1 result.");
+ args[0] = &ts1_type;
+ values[0] = &ts1_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ts1_type, args) == FFI_OK);
+
+ ts1_arg.uc = '\x01';
+ ts1_arg.d = 3.14159;
+ ts1_arg.ui = 555;
+
+ ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
+
+ CHECK(ts1_result->ui == 556);
+ CHECK(ts1_result->d == 3.14159 - 1);
+
+ puts ("structure test 1 ok!\n");
+
+ free (ts1_result);
+ }
+
+ /* struct tests */
+ {
+ test_structure_2 ts2_arg;
+
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_2 *ts2_result =
+ (test_structure_2 *) malloc (sizeof(test_structure_2));
+
+ args[0] = &ts2_type;
+ values[0] = &ts2_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ts2_type, args) == FFI_OK);
+
+ ts2_arg.d1 = 5.55;
+ ts2_arg.d2 = 6.66;
+
+ printf ("%g\n", ts2_result->d1);
+ printf ("%g\n", ts2_result->d2);
+
+ ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
+
+ printf ("%g\n", ts2_result->d1);
+ printf ("%g\n", ts2_result->d2);
+
+ CHECK(ts2_result->d1 == 5.55 - 1);
+ CHECK(ts2_result->d2 == 6.66 - 1);
+
+ printf("structure test 2 ok!\n");
+
+ free (ts2_result);
+ }
+
+ /* struct tests */
+ {
+ int compare_value;
+ test_structure_3 ts3_arg;
+ test_structure_3 *ts3_result =
+ (test_structure_3 *) malloc (sizeof(test_structure_3));
+
+ args[0] = &ts3_type;
+ values[0] = &ts3_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ts3_type, args) == FFI_OK);
+
+ ts3_arg.si = -123;
+ compare_value = ts3_arg.si;
+
+ ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
+
+ printf ("%d %d\n", ts3_result->si, -(compare_value*2));
+
+ if (ts3_result->si == -(ts3_arg.si*2))
+ puts ("structure test 3 ok!");
+ else
+ {
+ puts ("Structure test 3 found structure passing bug.");
+ puts (" Current versions of GCC are not 100% compliant with the");
+ puts (" n32 ABI. There is a known problem related to passing");
+ puts (" small structures. Send a bug report to the gcc maintainers.");
+ }
+
+ free (ts3_result);
+ }
+
+ /* struct tests */
+ {
+ test_structure_4 ts4_arg;
+
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_4 *ts4_result =
+ (test_structure_4 *) malloc (sizeof(test_structure_4));
+
+ args[0] = &ts4_type;
+ values[0] = &ts4_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ts4_type, args) == FFI_OK);
+
+ ts4_arg.ui1 = 2;
+ ts4_arg.ui2 = 3;
+ ts4_arg.ui3 = 4;
+
+ ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
+
+ if (ts4_result->ui3 == 2U * 3U * 4U)
+ puts ("structure test 4 ok!");
+ else
+ puts ("Structure test 4 found GCC's structure passing bug.");
+
+ free (ts4_result);
+ }
+
+ /* struct tests */
+ {
+ test_structure_5 ts5_arg1, ts5_arg2;
+
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_5 *ts5_result =
+ (test_structure_5 *) malloc (sizeof(test_structure_5));
+
+ args[0] = &ts5_type;
+ args[1] = &ts5_type;
+ values[0] = &ts5_arg1;
+ values[1] = &ts5_arg2;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+ &ts5_type, args) == FFI_OK);
+
+ ts5_arg1.c1 = 2;
+ ts5_arg1.c2 = 6;
+ ts5_arg2.c1 = 5;
+ ts5_arg2.c2 = 3;
+
+ ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
+
+ if (ts5_result->c1 == 7
+ && ts5_result->c2 == 3)
+ puts ("structure test 5 ok!");
+ else
+ puts ("Structure test 5 found GCC's structure passing bug.");
+
+ free (ts5_result);
+ }
+
+# if FFI_CLOSURES
+ /* A simple closure test */
+ {
+ ffi_closure cl;
+ ffi_type * cl_arg_types[3];
+
+ cl_arg_types[0] = &ffi_type_sint;
+ cl_arg_types[1] = &ffi_type_float;
+ cl_arg_types[2] = NULL;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+ &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+ CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
+ (void *) 3 /* userdata */)
+ == FFI_OK);
+ CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
+ }
+# endif
+
+ /* If we arrived here, all is good */
+ (void) puts("\nLooks good. No surprises.\n");
+
+ /*@-compdestroy@*/
+
+ return 0;
+}
+
diff --git a/c/src/tests/libffi/ffitest/init.c b/c/src/tests/libffi/ffitest/init.c
new file mode 100644
index 0000000000..30086c51c2
--- /dev/null
+++ b/c/src/tests/libffi/ffitest/init.c
@@ -0,0 +1,35 @@
+/* Init
+ *
+ * This routine is the initialization task for this test program.
+ * It is called from init_exec and has the responsibility for creating
+ * and starting the tasks that make up the test. If the time of day
+ * clock is required for the test, it should also be set to a known
+ * value by this function.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ */
+
+#define TEST_INIT
+#include "system.h"
+
+extern int ffi_main ( void );
+
+rtems_task Init(
+ rtems_task_argument ignored
+)
+{
+ printf( "\n\n*** LIBFFI TEST ***\n" );
+ ffi_main();
+ printf( "*** END OF LIBFFI TEST ***\n" );
+ exit( 0 );
+} \ No newline at end of file
diff --git a/c/src/tests/libffi/ffitest/system.h b/c/src/tests/libffi/ffitest/system.h
new file mode 100644
index 0000000000..45163f3596
--- /dev/null
+++ b/c/src/tests/libffi/ffitest/system.h
@@ -0,0 +1,36 @@
+/* system.h
+ *
+ * This include file contains information that is included in every
+ * function in the test set.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <tmacros.h>
+
+/* functions */
+
+rtems_task Init(
+ rtems_task_argument argument
+);
+
+/* configuration information */
+
+#define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+
+#include <confdefs.h>
+
+/* global variables */
+
+TEST_EXTERN rtems_id Global_variable; /* example global variable */
+
+/* end of include file */
diff --git a/c/src/tests/libffi/libffi.am b/c/src/tests/libffi/libffi.am
new file mode 100644
index 0000000000..577bac9fd2
--- /dev/null
+++ b/c/src/tests/libffi/libffi.am
@@ -0,0 +1,11 @@
+project_bspdir=$(PROJECT_ROOT)/@RTEMS_BSP@
+
+$(project_bspdir)/tests:
+ @$(mkinstalldirs) $@
+
+$(project_bspdir)/tests/$(TEST)$(LIB_VARIANT).exe: $(PGM)
+ $(INSTALL_PROGRAM) $< $@
+
+TMPINSTALL_FILES += \
+$(project_bspdir)/tests \
+$(project_bspdir)/tests/$(TEST)$(LIB_VARIANT).exe
diff --git a/c/src/tests/sptests/threaditerate/Makefile.am b/c/src/tests/sptests/threaditerate/Makefile.am
new file mode 100644
index 0000000000..b52b949e2c
--- /dev/null
+++ b/c/src/tests/sptests/threaditerate/Makefile.am
@@ -0,0 +1,43 @@
+##
+## $Id$
+##
+
+AUTOMAKE_OPTIONS = foreign 1.4
+TEST = threaditerate
+
+MANAGERS = all
+
+C_FILES = init.c threadinfo.c rtemstask.c pthread.c itron_task.c
+C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o)
+
+H_FILES = system.h
+noinst_HEADERS =$(H_FILES)
+
+DOCTYPES = scn doc
+DOCS = $(DOCTYPES:%=$(TEST).%)
+
+SRCS = $(C_FILES) $(H_FILES)
+OBJS = $(C_O_FILES)
+
+PRINT_SRCS = $(DOCS)
+
+PGM = ${ARCH}/$(TEST).exe
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+include $(top_srcdir)/sptests.am
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+AM_CPPFLAGS = -I$(top_srcdir)/../psxtests/include
+
+${PGM}: $(OBJS) $(LINK_FILES)
+ $(make-exe)
+
+all: $(ARCH) $(TMPINSTALL_FILES)
+
+EXTRA_DIST = $(C_FILES) $(DOCS)
+
+include $(top_srcdir)/../../../../automake/local.am
diff --git a/c/src/tests/sptests/threaditerate/init.c b/c/src/tests/sptests/threaditerate/init.c
new file mode 100644
index 0000000000..58743986af
--- /dev/null
+++ b/c/src/tests/sptests/threaditerate/init.c
@@ -0,0 +1,202 @@
+/* Init
+ *
+ * This routine is the initialization task for this test program.
+ * It is a user initialization task and has the responsibility for creating
+ * and starting the tasks that make up the test. If the time of day
+ * clock is required for the test, it should also be set to a known
+ * value by this function.
+ *
+ * Input parameters:
+ * argument - task argument
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#define TEST_INIT
+#include "system.h"
+
+rtems_task Init(
+ rtems_task_argument argument
+)
+{
+ rtems_time_of_day time;
+ rtems_status_code rtems_status;
+
+#ifdef RTEMS_POSIX_API
+ int posix_status;
+#endif
+
+#ifdef RTEMS_ITRON_API
+ ER itron_status;
+ T_CTSK pk_ctsk;
+#endif
+
+ puts( "\n\n*** Thread Iteration Test ***" );
+
+ build_time( &time, 12, 31, 2000, 9, 0, 0, 0 );
+ rtems_status = rtems_clock_set( &time );
+ directive_failed( rtems_status, "rtems_clock_set" );
+
+ Task_name[ 1 ] = rtems_build_name( 'T', 'A', '1', ' ' );
+ Task_name[ 2 ] = rtems_build_name( 'T', 'A', '2', ' ' );
+ Task_name[ 3 ] = rtems_build_name( 'T', 'A', '3', ' ' );
+
+ rtems_status = rtems_task_create(
+ Task_name[ 1 ],
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE * 2,
+ RTEMS_INTERRUPT_LEVEL(31),
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &Task_id[ 1 ]
+ );
+ directive_failed( rtems_status, "rtems_task_create of TA1" );
+
+ rtems_status = rtems_task_create(
+ Task_name[ 2 ],
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE * 2,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &Task_id[ 2 ]
+ );
+ directive_failed( rtems_status, "rtems_task_create of TA2" );
+
+ rtems_status = rtems_task_create(
+ Task_name[ 3 ],
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE * 3,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &Task_id[ 3 ]
+ );
+ directive_failed( rtems_status, "rtems_task_create of TA3" );
+
+ rtems_status = rtems_task_start( Task_id[ 1 ], RTEMS_task_1_through_3, 0 );
+ if ( rtems_status == RTEMS_SUCCESSFUL )
+ printf("Created and started an RTEMS task with id = 0x%08x\n", Task_id[1] );
+ else
+ directive_failed( rtems_status, "rtems_task_start of TA1" );
+
+ rtems_status = rtems_task_start( Task_id[ 2 ], RTEMS_task_1_through_3, 0 );
+ if ( rtems_status == RTEMS_SUCCESSFUL )
+ printf("Created and started an RTEMS task with id = 0x%08x\n", Task_id[2] );
+ else
+ directive_failed( rtems_status, "rtems_task_start of TA2" );
+
+ rtems_status = rtems_task_start( Task_id[ 3 ], RTEMS_task_1_through_3, 0 );
+ if ( rtems_status == RTEMS_SUCCESSFUL )
+ printf("Created and started an RTEMS task with id = 0x%08x\n", Task_id[3] );
+ else
+ directive_failed( rtems_status, "rtems_task_start of TA3" );
+
+#ifdef RTEMS_POSIX_API
+ posix_status = pthread_create( &pthread_id[0], NULL, pthread_1_through_3, NULL );
+ if ( !posix_status )
+ printf("Created and started a pthread with id = 0x%08x\n", pthread_id[0] );
+ else
+ assert( !posix_status );
+
+ posix_status = pthread_create( &pthread_id[1], NULL, pthread_1_through_3, NULL );
+ if ( !posix_status )
+ printf("Created and started a pthread with id = 0x%08x\n", pthread_id[1] );
+ else
+ assert( !posix_status );
+
+ posix_status = pthread_create( &pthread_id[2], NULL, pthread_1_through_3, NULL );
+ if ( !posix_status )
+ printf("Created and started a pthread with id = 0x%08x\n", pthread_id[2] );
+ else
+ assert( !posix_status );
+
+#endif
+
+#ifdef RTEMS_ITRON_API
+
+#define ITRON_GET_TASK_ID(_index) \
+ _ITRON_Task_Information.local_table[_index]->id
+
+ pk_ctsk.exinf = NULL;
+ pk_ctsk.tskatr = TA_HLNG;
+ pk_ctsk.itskpri = 1;
+ pk_ctsk.task = ITRON_task_2_through_4;
+ pk_ctsk.stksz = RTEMS_MINIMUM_STACK_SIZE * 2;
+
+ itron_status = cre_tsk( 2, &pk_ctsk );
+ directive_failed( itron_status, "cre_tsk of task" );
+
+ pk_ctsk.stksz = RTEMS_MINIMUM_STACK_SIZE * 2;
+ itron_status = cre_tsk( 3, &pk_ctsk );
+ directive_failed( itron_status, "cre_tsk of TA2" );
+
+ pk_ctsk.stksz = RTEMS_MINIMUM_STACK_SIZE * 3;
+ itron_status = cre_tsk( 4, &pk_ctsk );
+ directive_failed( itron_status, "cre_tsk of TA3" );
+
+ itron_status = sta_tsk( 2, 0 );
+ if ( !itron_status )
+ printf("Created and started an ITRON task with id = 0x%08x\n", ITRON_GET_TASK_ID( 2 ) );
+ else
+ directive_failed( itron_status, "sta_tsk of ITRON task 2" );
+
+ itron_status = sta_tsk( 3, 0 );
+ if ( !itron_status )
+ printf("Created and started an ITRON task with id = 0x%08x\n", ITRON_GET_TASK_ID( 3 ) );
+ else
+ directive_failed( itron_status, "sta_tsk of ITRON task 3" );
+
+ itron_status = sta_tsk( 4, 0 );
+ if ( !itron_status )
+ printf("Created and started an ITRON task with id = 0x%08x\n", ITRON_GET_TASK_ID( 4 ) );
+ else
+ directive_failed( itron_status, "sta_tsk of ITRON task 4" );
+#endif
+
+ printf( "Sleeping for 5 seconds\n" );
+ fflush( stdout );
+
+ rtems_status = rtems_task_wake_after( 5 * TICKS_PER_SECOND );
+ directive_failed( rtems_status, "rtems_task_wake_after" );
+
+ printf( "\nLooking for all threads\n\n" );
+ _Thread_Local_iterate( print_thread_info, NULL, FALSE );
+
+ printf( "That was it. Sleeping for 20 seconds.\n" );
+
+ rtems_status = rtems_task_wake_after( 20 * TICKS_PER_SECOND );
+ directive_failed( rtems_status, "rtems_task_wake_after" );
+
+ /* If we get here, all threads were created */
+ printf( "\nDeleting the second thread of each type\n\n" );
+
+ rtems_status = rtems_task_suspend( Task_id[2] );
+ directive_failed( rtems_status, "rtems_task_suspend" );
+ rtems_status = rtems_task_delete( Task_id[2] );
+ directive_failed( rtems_status, "rtems_task_delete" );
+
+#ifdef RTEMS_POSIX_API
+ posix_status = pthread_cancel( pthread_id[2] );
+ assert( !posix_status );
+#endif
+
+#ifdef RTEMS_ITRON_API
+ itron_status = ter_tsk( 3 );
+ directive_failed( itron_status, "ter_tsk of ITRON task 3" );
+#endif
+
+ printf( "\nLooking for all threads\n\n" );
+ _Thread_Local_iterate( print_thread_info, NULL, FALSE );
+
+ printf( "That was it. Exiting\n" );
+ fflush( stdout );
+
+ exit( 0 );
+}
diff --git a/c/src/tests/sptests/threaditerate/itrontask.c b/c/src/tests/sptests/threaditerate/itrontask.c
new file mode 100644
index 0000000000..8ae8364d66
--- /dev/null
+++ b/c/src/tests/sptests/threaditerate/itrontask.c
@@ -0,0 +1,52 @@
+/* Task_1_through_3
+ *
+ * This routine serves as a test task. It verifies the basic task
+ * switching capabilities of the executive.
+ *
+ * Input parameters:
+ * argument - task argument
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "system.h"
+
+void ITRON_task_2_through_4( void )
+{
+ ID tid;
+ int tid_index;
+ rtems_time_of_day time;
+ ER status;
+ char name[30];
+
+ status = get_tid( &tid );
+ directive_failed( status, "get_tid");
+
+ tid_index = tid - 1; /* account for init tasks */
+
+ status = rtems_task_wake_after( 10 * TICKS_PER_SECOND );
+ directive_failed( status, "rtems_task_wake_after" );
+
+ sprintf(name, "ITRON task %d", tid_index);
+
+ while( FOREVER ) {
+ status = rtems_clock_get( RTEMS_CLOCK_GET_TOD, &time );
+ directive_failed( status, "rtems_clock_get" );
+
+ printf(name);
+ print_time( " - rtems_clock_get - ", &time, "\n" );
+
+ status = rtems_task_wake_after( 30 * TICKS_PER_SECOND );
+ directive_failed( status, "rtems_task_wake_after" );
+ }
+}
+
diff --git a/c/src/tests/sptests/threaditerate/pthread.c b/c/src/tests/sptests/threaditerate/pthread.c
new file mode 100644
index 0000000000..0dd76fcb91
--- /dev/null
+++ b/c/src/tests/sptests/threaditerate/pthread.c
@@ -0,0 +1,46 @@
+/* pthread_1_through_3
+ *
+ * This routine serves as a test task. It verifies the basic task
+ * switching capabilities of the executive.
+ *
+ * Input parameters:
+ * argument - task argument
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "system.h"
+#include <sys/utsname.h>
+
+void * pthread_1_through_3( void *argument )
+{
+ int status;
+ struct timespec tv;
+ struct timespec tr;
+ time_t remaining;
+
+ remaining = sleep( 10 );
+ assert( !remaining );
+
+ while( FOREVER ) {
+ status = clock_gettime( CLOCK_REALTIME, &tv );
+ posix_service_failed( status, "clock_gettime" );
+
+ printf( "pthread: ID is 0x%08x\n", pthread_self() );
+ printf( " - clock_gettime - %s\n", ctime( &tv.tv_sec ) );
+
+ remaining = sleep( 30 );
+ assert( !remaining );
+ }
+
+ return NULL; /* just so the compiler thinks we returned something */
+}
diff --git a/c/src/tests/sptests/threaditerate/rtemstask.c b/c/src/tests/sptests/threaditerate/rtemstask.c
new file mode 100644
index 0000000000..4a15ebec5f
--- /dev/null
+++ b/c/src/tests/sptests/threaditerate/rtemstask.c
@@ -0,0 +1,47 @@
+/* Task_1_through_3
+ *
+ * This routine serves as a test task. It verifies the basic task
+ * switching capabilities of the executive.
+ *
+ * Input parameters:
+ * argument - task argument
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "system.h"
+
+rtems_task RTEMS_task_1_through_3(
+ rtems_task_argument argument
+)
+{
+ rtems_id tid;
+ rtems_time_of_day time;
+ rtems_status_code status;
+
+ status = rtems_task_ident( RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &tid );
+ directive_failed( status, "rtems_task_ident" );
+
+ status = rtems_task_wake_after( 10 * TICKS_PER_SECOND );
+ directive_failed( status, "rtems_task_wake_after" );
+
+ while( FOREVER ) {
+ status = rtems_clock_get( RTEMS_CLOCK_GET_TOD, &time );
+ directive_failed( status, "rtems_clock_get" );
+
+ put_name( Task_name[ task_number( tid ) ], FALSE );
+ print_time( " - rtems_clock_get - ", &time, "\n" );
+
+ status = rtems_task_wake_after( 30 * TICKS_PER_SECOND );
+ directive_failed( status, "rtems_task_wake_after" );
+ }
+}
diff --git a/c/src/tests/sptests/threaditerate/system.h b/c/src/tests/sptests/threaditerate/system.h
new file mode 100644
index 0000000000..7792073f62
--- /dev/null
+++ b/c/src/tests/sptests/threaditerate/system.h
@@ -0,0 +1,98 @@
+/* system.h
+ *
+ * This include file contains information that is included in every
+ * function in the test set.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+/* RTEMS API */
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+
+unsigned32 print_thread_info( Thread_Control *thread, void * arg );
+
+#include <tmacros.h>
+
+/* functions */
+
+rtems_task Init( rtems_task_argument argument );
+rtems_task RTEMS_task_1_through_3( rtems_task_argument argument );
+
+/* global variables */
+
+TEST_EXTERN rtems_id Task_id[ 4 ]; /* array of task ids */
+TEST_EXTERN rtems_name Task_name[ 4 ]; /* array of task names */
+
+/* configuration information */
+
+#define CONFIGURE_SPTEST
+
+#define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_TEST_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_EXTRA_TASK_STACKS (4 * RTEMS_MINIMUM_STACK_SIZE)
+
+
+
+/* POSIX API */
+
+#ifdef RTEMS_POSIX_API
+
+#include <pmacros.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sched.h>
+
+/* functions */
+
+void *pthread_1_through_3( void *argument );
+
+/* global variables */
+
+TEST_EXTERN pthread_t pthread_id[3]; /* array of pthread ids */
+
+/* configuration information */
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 3
+
+#endif
+
+
+
+/* ITRON API */
+
+#ifdef RTEMS_ITRON_API
+
+#include <itron.h>
+#include <rtems/itron/task.h>
+
+/* functions */
+
+void ITRON_task_2_through_4( void );
+
+/* global variables */
+
+TEST_EXTERN Objects_Locations location;
+
+
+/* configuration information */
+
+#endif
+
+#include <confdefs.h>
+
+/* end of include file */
diff --git a/c/src/tests/sptests/threaditerate/threadinfo.c b/c/src/tests/sptests/threaditerate/threadinfo.c
new file mode 100644
index 0000000000..baf4822a5a
--- /dev/null
+++ b/c/src/tests/sptests/threaditerate/threadinfo.c
@@ -0,0 +1,178 @@
+/* threadinfo.c
+ *
+ * Routines to print out information about threads.
+ */
+
+#include "system.h"
+#include <stdlib.h>
+
+#define PTR unsigned int
+#define PTR_MASK "0x%08x"
+
+/*
+ * Return a pointer to a string describing the object type.
+ */
+
+const char * _Objects_Type_to_String( Objects_Control * object )
+{
+ switch( _Objects_Get_class( object->id ) ) {
+ case OBJECTS_NO_CLASS:
+ return "NO_CLASS";
+
+ case OBJECTS_INTERNAL_THREADS:
+ return "INTERNAL_THREADS";
+
+ case OBJECTS_RTEMS_TASKS:
+ return "RTEMS_TASKS";
+
+ case OBJECTS_POSIX_THREADS:
+ return "POSIX_THREADS";
+
+ case OBJECTS_ITRON_TASKS:
+ return "ITRON_TASKS";
+
+ case OBJECTS_RTEMS_TIMERS:
+ return "RTEMS_TIMERS";
+
+ case OBJECTS_RTEMS_SEMAPHORES:
+ return "RTEMS_SEMAPHORES";
+
+ case OBJECTS_RTEMS_MESSAGE_QUEUES:
+ return "RTEMS_MESSAGE_QUEUES";
+
+ case OBJECTS_RTEMS_PARTITIONS:
+ return "RTEMS_PARTITIONS";
+
+ case OBJECTS_RTEMS_REGIONS:
+ return "RTEMS_REGIONS";
+
+ case OBJECTS_RTEMS_PORTS:
+ return "RTEMS_PORTS";
+
+ case OBJECTS_RTEMS_PERIODS:
+ return "RTEMS_PERIODS";
+
+ case OBJECTS_RTEMS_EXTENSIONS:
+ return "RTEMS_EXTENSIONS";
+
+ case OBJECTS_POSIX_KEYS:
+ return "POSIX_KEYS";
+
+ case OBJECTS_POSIX_INTERRUPTS:
+ return "POSIX_INTERRUPTS";
+
+ case OBJECTS_POSIX_MESSAGE_QUEUES:
+ return "POSIX_MESSAGE_QUEUES";
+
+ case OBJECTS_POSIX_MUTEXES:
+ return "POSIX_MUTEXES";
+
+ case OBJECTS_POSIX_SEMAPHORES:
+ return "POSIX_SEMAPHORES";
+
+ case OBJECTS_POSIX_CONDITION_VARIABLES:
+ return "POSIX_CONDITION_VARIABLES";
+
+ case OBJECTS_ITRON_EVENTFLAGS:
+ return "ITRON_EVENTFLAGS";
+
+ case OBJECTS_ITRON_MAILBOXES:
+ return "ITRON_MAILBOXES";
+
+ case OBJECTS_ITRON_MESSAGE_BUFFERS:
+ return "ITRON_MESSAGE_BUFFERS";
+
+ case OBJECTS_ITRON_PORTS:
+ return "ITRON_PORTS";
+
+ case OBJECTS_ITRON_SEMAPHORES:
+ return "ITRON_SEMAPHORES";
+
+ case OBJECTS_ITRON_VARIABLE_MEMORY_POOLS:
+ return "ITRON_VARIABLE_MEMORY_POOLS";
+
+ case OBJECTS_ITRON_FIXED_MEMORY_POOLS:
+ return "ITRON_FIXED_MEMORY_POOLS";
+
+ default:
+ return "UNKNOWN";
+ }
+}
+
+
+/*
+ * Return a pointer to a string describing the thread state
+ */
+
+const char * _Thread_State_to_String( States_Control state )
+{
+ States_Control orig_state = state;
+ int i;
+ int first_entry = TRUE;
+ static char buffer[256];
+ static const char *desc[] = {
+ "READY", /* 0 - 0x00000 */
+ "DORMANT", /* 1 - 0x00001 */
+ "SUSPENDED", /* 2 - 0x00002 */
+ "TRANSIENT", /* 3 - 0x00004 */
+ "DELAYING", /* 4 - 0x00008 */
+ "WAITING_FOR_TIME", /* 5 - 0x00010 */
+ "WAITING_FOR_BUFFER", /* 6 - 0x00020 */
+ "WAITING_FOR_SEGMENT", /* 7 - 0x00040 */
+ "WAITING_FOR_MESSAGE", /* 8 - 0x00080 */
+ "WAITING_FOR_EVENT", /* 9 - 0x00100 */
+ "WAITING_FOR_SEMAPHORE", /* 10 - 0x00200 */
+ "WAITING_FOR_MUTEX", /* 11 - 0x00400 */
+ "WAITING_FOR_CONDITION_VARIABLE", /* 12 - 0x00800 */
+ "WAITING_FOR_JOIN_AT_EXIT", /* 13 - 0x01000 */
+ "WAITING_FOR_RPC_REPLY", /* 14 - 0x02000 */
+ "WAITING_FOR_PERIOD", /* 15 - 0x04000 */
+ "WAITING_FOR_SIGNAL", /* 16 - 0x08000 */
+ "INTERRUPTIBLE_BY_SIGNAL", /* 17 - 0x10000 */
+ "UNKNOWN" /* 18 - all higher bits */
+ };
+
+ if( state == STATES_READY )
+ return desc[0];
+
+ memset( buffer, '\0', sizeof( buffer ) );
+ for ( i = 1; i < 18; i++ ) {
+ if ( state & 0x1 ) {
+ if ( !first_entry ) {
+ strcat ( buffer, " | " );
+ }
+ strcat ( buffer, desc[i] );
+ first_entry = FALSE;
+ }
+ state = state >> 1;
+ }
+
+ if ( state != 0 ) {
+ if ( !first_entry ) {
+ strcat ( buffer, " | " );
+ }
+ strcat ( buffer, desc[18] );
+ }
+
+ return buffer;
+}
+
+
+/*
+ * Callback function to print out thread Ids, thread priorities, and thread stack
+ * information.
+ */
+
+unsigned32 print_thread_info( Thread_Control *thread, void * arg )
+{
+ printf( "Thread ID 0x%08x at "PTR_MASK"\n", thread->Object.id, (PTR)thread );
+ printf( "\ttype = %s\n", _Objects_Type_to_String( &(thread->Object) ) );
+ printf( "\tstate = %s\n", _Thread_State_to_String( thread->current_state ) );
+ printf( "\treal priority = %d\n", thread->real_priority );
+ printf( "\tcurrent priority = %d\n", thread->current_priority );
+ printf( "\tstack base = "PTR_MASK"\n", (PTR)thread->Start.Initial_stack.area );
+ printf( "\tstack size = 0x%08x\n", thread->Start.Initial_stack.size );
+ /* printf( "\tstack pointer = "PTR_MASK"\n", */
+ printf( "\n" );
+ return 0;
+}
diff --git a/c/src/tests/sptests/threaditerate/threaditerate.scn b/c/src/tests/sptests/threaditerate/threaditerate.scn
new file mode 100644
index 0000000000..9aeb43a212
--- /dev/null
+++ b/c/src/tests/sptests/threaditerate/threaditerate.scn
@@ -0,0 +1,205 @@
+*** Thread Iteration Test ***
+Created and started an RTEMS task with id = 0x08010002
+Created and started an RTEMS task with id = 0x08010003
+Created and started an RTEMS task with id = 0x08010004
+Created and started a pthread with id = 0x0c010001
+Created and started a pthread with id = 0x0c010002
+Created and started a pthread with id = 0x0c010003
+Created and started an ITRON task with id = 0x10010002
+Created and started an ITRON task with id = 0x10010003
+Created and started an ITRON task with id = 0x10010004
+Sleeping for 5 seconds
+
+Looking for all threads
+
+Thread ID 0x04010001 at 0x00192364
+ type = INTERNAL_THREADS
+ state = READY
+ real priority = 255
+ current priority = 255
+ stack base = 0x0018cde8
+ stack size = 0x00002008
+
+Thread ID 0x08010001 at 0x00191390
+ type = RTEMS_TASKS
+ state = READY
+ real priority = 1
+ current priority = 1
+ stack base = 0x0018ac54
+ stack size = 0x00002008
+
+Thread ID 0x08010002 at 0x001914ec
+ type = RTEMS_TASKS
+ state = DELAYING
+ real priority = 1
+ current priority = 1
+ stack base = 0x00186ac0
+ stack size = 0x00004008
+
+Thread ID 0x08010003 at 0x00191648
+ type = RTEMS_TASKS
+ state = DELAYING
+ real priority = 1
+ current priority = 1
+ stack base = 0x0018292c
+ stack size = 0x00004008
+
+Thread ID 0x08010004 at 0x001917a4
+ type = RTEMS_TASKS
+ state = DELAYING
+ real priority = 1
+ current priority = 1
+ stack base = 0x0017c798
+ stack size = 0x00006008
+
+Thread ID 0x0c010001 at 0x0018fbf4
+ type = POSIX_THREADS
+ state = DELAYING | INTERRUPTIBLE_BY_SIGNAL
+ real priority = 1
+ current priority = 1
+ stack base = 0x00178604
+ stack size = 0x00004008
+
+Thread ID 0x0c010002 at 0x0018fd50
+ type = POSIX_THREADS
+ state = DELAYING | INTERRUPTIBLE_BY_SIGNAL
+ real priority = 1
+ current priority = 1
+ stack base = 0x00174470
+ stack size = 0x00004008
+
+Thread ID 0x0c010003 at 0x0018feac
+ type = POSIX_THREADS
+ state = DELAYING | INTERRUPTIBLE_BY_SIGNAL
+ real priority = 1
+ current priority = 1
+ stack base = 0x001702dc
+ stack size = 0x00004008
+
+Thread ID 0x10010002 at 0x0018ef58
+ type = ITRON_TASKS
+ state = DELAYING
+ real priority = 1
+ current priority = 1
+ stack base = 0x0016c148
+ stack size = 0x00004008
+
+Thread ID 0x10010003 at 0x0018f0b4
+ type = ITRON_TASKS
+ state = DELAYING
+ real priority = 1
+ current priority = 1
+ stack base = 0x00167f24
+ stack size = 0x00004008
+
+Thread ID 0x10010004 at 0x0018f210
+ type = ITRON_TASKS
+ state = DELAYING
+ real priority = 1
+ current priority = 1
+ stack base = 0x00161d00
+ stack size = 0x00006008
+
+That was it. Sleeping for 20 seconds.
+TA1 - rtems_clock_get - 09:00:10 12/31/2000
+TA2 - rtems_clock_get - 09:00:10 12/31/2000
+TA3 - rtems_clock_get - 09:00:10 12/31/2000
+pthread: ID is 0x0c010001
+ - clock_gettime - Sun Dec 31 09:00:10 2000
+
+pthread: ID is 0x0c010002
+ - clock_gettime - Sun Dec 31 09:00:10 2000
+
+pthread: ID is 0x0c010003
+ - clock_gettime - Sun Dec 31 09:00:10 2000
+ITRON task 1 - rtems_clock_get - 09:00:10 12/31/2000
+
+ITRON task 2 - rtems_clock_get - 09:00:10 12/31/2000
+ITRON task 3 - rtems_clock_get - 09:00:10 12/31/2000
+
+Deleting the second thread of each type
+
+
+Looking for all threads
+
+Thread ID 0x04010001 at 0x00192364
+ type = INTERNAL_THREADS
+ state = READY
+ real priority = 255
+ current priority = 255
+ stack base = 0x0018cde8
+ stack size = 0x00002008
+
+Thread ID 0x08010001 at 0x00191390
+ type = RTEMS_TASKS
+ state = READY
+ real priority = 1
+ current priority = 1
+ stack base = 0x0018ac54
+ stack size = 0x00002008
+
+Thread ID 0x08010002 at 0x001914ec
+ type = RTEMS_TASKS
+ state = DELAYING
+ real priority = 1
+ current priority = 1
+ stack base = 0x00186ac0
+ stack size = 0x00004008
+
+Thread ID 0x08010004 at 0x001917a4
+ type = RTEMS_TASKS
+ state = DELAYING
+ real priority = 1
+ current priority = 1
+ stack base = 0x0017c798
+ stack size = 0x00006008
+
+Thread ID 0x0c010001 at 0x0018fbf4
+ type = POSIX_THREADS
+ state = DELAYING | INTERRUPTIBLE_BY_SIGNAL
+ real priority = 1
+ current priority = 1
+ stack base = 0x00178604
+ stack size = 0x00004008
+
+Thread ID 0x0c010002 at 0x0018fd50
+ type = POSIX_THREADS
+ state = DELAYING | INTERRUPTIBLE_BY_SIGNAL
+ real priority = 1
+ current priority = 1
+ stack base = 0x00174470
+ stack size = 0x00004008
+
+Thread ID 0x0c010003 at 0x0018feac
+ type = POSIX_THREADS
+ state = DELAYING | INTERRUPTIBLE_BY_SIGNAL
+ real priority = 1
+ current priority = 1
+ stack base = 0x001702dc
+ stack size = 0x00004008
+
+Thread ID 0x10010002 at 0x0018ef58
+ type = ITRON_TASKS
+ state = DELAYING
+ real priority = 1
+ current priority = 1
+ stack base = 0x0016c148
+ stack size = 0x00004008
+
+Thread ID 0x10010003 at 0x0018f0b4
+ type = ITRON_TASKS
+ state = DORMANT
+ real priority = 1
+ current priority = 1
+ stack base = 0x00167f24
+ stack size = 0x00004008
+
+Thread ID 0x10010004 at 0x0018f210
+ type = ITRON_TASKS
+ state = DELAYING
+ real priority =1
+ current priority = 1
+ stack base = 0x00161d00
+ stack size = 0x00006008
+
+That was it. Exiting
diff --git a/make/custom/mbx821_001.cfg b/make/custom/mbx821_001.cfg
new file mode 100644
index 0000000000..8f8a3327f6
--- /dev/null
+++ b/make/custom/mbx821_001.cfg
@@ -0,0 +1,12 @@
+#
+# Config file for a PowerPC MPC860-based MBX821-001 card.
+#
+
+#
+# All MBX8xx configurations share the same base file, only a few
+# parameters differ.
+#
+
+RTEMS_MBX_MODEL=mbx821_001
+
+include $(RTEMS_ROOT)/make/custom/mbx8xx.cfg
diff --git a/make/custom/mbx860_002.cfg b/make/custom/mbx860_002.cfg
new file mode 100644
index 0000000000..0558456004
--- /dev/null
+++ b/make/custom/mbx860_002.cfg
@@ -0,0 +1,12 @@
+#
+# Config file for a PowerPC MPC860-based MBX860-002 card.
+#
+
+#
+# All MBX8xx configurations share the same base file, only a few
+# parameters differ.
+#
+
+RTEMS_MBX_MODEL=mbx860_002
+
+include $(RTEMS_ROOT)/make/custom/mbx8xx.cfg
diff --git a/make/custom/mbx8xx.cfg b/make/custom/mbx8xx.cfg
new file mode 100644
index 0000000000..f868c2fb52
--- /dev/null
+++ b/make/custom/mbx8xx.cfg
@@ -0,0 +1,196 @@
+#
+# Config file for a PowerPC MPC821- or MPC860-based MBX card
+#
+# This file is derived from:
+#
+# Config file for a PowerPC 403 based helas403 card
+# Config file for MPC860 based Ethernet Comm Board
+#
+
+include $(RTEMS_ROOT)/make/custom/default.cfg
+
+RTEMS_CPU=powerpc
+RTEMS_CPU_MODEL=mpc8xx
+
+# This is the actual bsp directory used during the build process.
+RTEMS_BSP_FAMILY=mbx8xx
+
+# The value assigned to RTEMS_CPU, RTEMS_CPU_MODEL and RTEMS_BSP get
+# #defined in targopts.h. Source code can switch on these values with #ifdef
+# to select what code to compile for a specific CPU family member and specific
+# board. The RTEMS_CPU_MODEL is also used as the name of the libcpu directory,
+# while the RTEMS_BSP_FAMILY is used as the name of the libbsp directory.
+# For the MBX860 and MBX821, the boards and processors are sufficiently
+# similar that the ports are unified and use RTEMS_CPU_MODEL=mpc8xx and
+# RTEMS_BSP_FAMILY=mbx8xx. Because there are minor differences in the CPUs
+# and the boards, it is necessary to specify them fully during the build.
+# Do a "make RTEMS_BSP=<your_board> <target>" See below for a list of valid
+# values for <your_board>.
+
+ifeq ($(findstring mbx821,$(RTEMS_MBX_MODEL)),mbx821)
+CPU_TYPE=821
+else
+ifeq ($(findstring mbx860,$(RTEMS_MBX_MODEL)),mbx860)
+CPU_TYPE=860
+else
+RTEMS_BSP = mbx860_002
+RTEMS_MBX_MODEL = mbx860_002
+TARGET_ARCH=o-mbx860_002
+CPU_TYPE=860
+endif # mbx860
+endif # mbx821
+
+# This section makes the target dependent options file.
+#
+# Note that RTEMS_BSP matches the RTEMS_MBX_MODEL. Its value must be
+# defined in targopts.h, so the few places that require different code
+# for different MBX models can be distinguished. The value of
+# RTEMS_BSP is already defined in targopts.h and is one of:
+# mbx860_001 mbx821_001
+# mbx860_002 mbx821_002
+# mbx860_003 mbx821_003
+# mbx860_004 mbx821_004
+# mbx860_005 mbx821_005
+# mbx860_001b mbx821_001b
+# mbx860_002b mbx821_002b
+# mbx860_003b mbx821_003b
+# mbx860_004b mbx821_004b
+# mbx860_005b mbx821_005b
+# mbx860_006b mbx821_006b
+
+# The specific CPU model is defined, so the few places that require
+# different code for the MPC860 and MPC821 can be distinguished.
+# Either mpc860 or mpc821 is defined.
+#
+# MBX8xx-specific options:
+#
+# CONSOLE_MINOR (BSP--console driver)
+# Must be defined to be one of SMC1_MINOR, SMC2_MINOR, SCC2_MINOR,
+# SCC3_MINOR, or SCC4_MINOR. Determines which device will be registered
+# as /dev/console.
+#
+# UARTS_USE_INTERRUPTS (BSP--console driver)
+# Define if you want interrupt-driven I/O instead of polling. Superceeded
+# by EPPCBUG_SMC1 on SMC1.
+#
+# EPPCBUG_SMC1 (BSP--console driver)
+# If defined, the I/O through the SCM1 is done through the EPPCBug firmware.
+# Because of limitations in revision 1.1 of the firmware, EPPCBug must be
+# configured to use SMC1 as its console. If not defined, I/O through SMC1
+# is done through a RTEMS device driver.
+#
+# EPPCBUG_VECTORS (BSP--RTEMS)
+# If defined, the most vectors branch to EPPCBug, except the following:
+# 0x500 (external interrupt), 0x900 (decrementer).
+#
+# INSTRUCTION_CACHE_ENABLE (BSP--RTEMS)
+# If defined, the instruction cache will be enabled after address translation
+# is turned on.
+#
+# DATA_CACHE_ENABLE (BSP--RTEMS)
+# If defined, the data cache will be enabled after address translation
+# is turned on.
+#
+# PowerPC-specific options:
+#
+# PPC_USE_SPRG (RTEMS PowerPC port)
+# If defined (=1), then the PowerPC specific code in RTEMS will use some
+# of the special purpose registers to slightly optimize interrupt
+# response time. The use of these registers can conflict with
+# other tools like debuggers. This should be 0 when using EPPCBug
+# because its uses most SPRGs (don't believe the documentation!).
+#
+# PPC_USE_DATA_CACHE (RTEMS PowerPC port)
+# If defined, then the PowerPC specific code in RTEMS will use
+# data cache instructions to optimize the context switch code.
+# This code can conflict with debuggers or emulators.
+#
+# RTEMS generic options:
+#
+# NDEBUG (C library)
+# If defined, asserts do not generate code. This is commonly used
+# as a command line option.
+#
+# RTEMS_TEST_NO_PAUSE (RTEMS tests)
+# If defined, do not pause between screens of output in the rtems tests.
+#
+# STACK_CHECKER_ON (RTEMS support code)
+# If defined, stack bounds checking is enabled.
+#
+# STACK_CHECKER_REPORT_USAGE (RTEMS support code)
+# If this and STACK_CHECKER_ON are defined, then a report on stack usage
+# per task is printed when the program exits.
+#
+# RTEMS_DEBUG (RTEMS)
+# If defined, debug checks in RTEMS and support library code are enabled.
+
+define make-target-options
+ @echo "#ifdef mpc$(CPU_TYPE)" >>$@
+ @echo "#undef mpc$(CPU_TYPE)" >>$@
+ @echo "#endif" >>$@
+ @echo "#define mpc$(CPU_TYPE) 1" >>$@
+ @echo >>$@
+ @echo "#define CONSOLE_MINOR SMC2_MINOR" >>$@
+ @echo "#define UARTS_USE_INTERRUPTS 1" >>$@
+ @echo "#define EPPCBUG_SMC1 1" >>$@
+ @echo "#define EPPCBUG_VECTORS 1" >>$@
+ @echo "#define INSTRUCTION_CACHE_ENABLE 1" >>$@
+ @echo "#define DATA_CACHE_ENABLE 1" >>$@
+ @echo >>$@
+ @echo "#define PPC_VECTOR_FILE_BASE 0x0000" >>$@
+ @echo "#define PPC_USE_SPRG 0" >>$@
+ @echo "/* #define PPC_USE_DATA_CACHE 1" */ >>$@
+ @echo >>$@
+ @echo "/* #define NDEBUG 1 */ " >>$@
+ @echo "#define RTEMS_TEST_NO_PAUSE 1" >>$@
+ @echo "/* #define STACK_CHECKER_ON 1 */" >>$@
+ @echo "/* #define STACK_CHECKER_REPORT_USAGE 1 */" >>$@
+ @echo "/* #define RTEMS_DEBUG 1 */" >>$@
+endef
+
+# This contains the compiler options necessary to select the CPU model
+# and (hopefully) optimize for it.
+#
+CPU_CFLAGS = -mcpu=$(CPU_TYPE)
+
+CFLAGS_DEBUG_V += -ggdb
+CXXFLAGS_DEBUG_V += -ggdb
+
+# optimize flag: typically -O, could use -O4 or -fast
+# -O4 is ok for RTEMS
+# NOTE: some level of -O may be actually required by inline assembler
+# CFLAGS_OPTIMIZE_V=-O4 -fno-keep-inline-functions
+CFLAGS_OPTIMIZE_V=-O4 -fno-keep-inline-functions
+CXXFLAGS_OPTIMIZE_V=-O4
+
+# The following are definitions of make-exe which will work using ld as
+# is currently required. It is expected that as of gcc 2.8, the end user
+# will be able to override parts of the compilers specs and link using gcc.
+
+ifeq ($(RTEMS_USE_GCC272),yes)
+# The --defsym arguments define arguments which are required by the linkcmds
+# file which is designed for gcc 2.8
+define make-exe
+ $(LD) $(XLDFLAGS) -T $(LINKCMDS) \
+ --defsym __fini=0 --defsym __init=0 \
+ -o $@ -u atexit -u __vectors -u start \
+ $(START_FILE) $(LINK_OBJS) --start-group $(LINK_LIBS) --end-group
+ $(NM) -g -n $@ > $(basename $@).num
+ $(STRIP) -o $(basename $@).elf $@
+ $(SIZE) $@
+endef
+else
+define make-exe
+ $(CC) $(CFLAGS) $(CPU_CFLAGS) $(XLDFLAGS) -o $(basename $@).exe \
+ $(LINK_OBJS) $(LINK_LIBS)
+ $(NM) -g -n $@ > $(basename $@).nm
+ $(STRIP) -o $(basename $@) $@
+ $(SIZE) $@
+endef
+endif
+
+# Miscellaneous additions go here
+
+# Override default start file
+START_BASE=
+