This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] cell spu offloading printf and friends


Patch checked in.

-- Jeff J.

jschopp wrote:
In the past I have sent out a series of patches that offloads various c99 stdio functions. The newlib stdio functions are simply too large for the cell spu. A simple hello world program will typically take in excess of 200K without this patch. Given the cell spu only has 256K in total it makes it totally impractical to add a printf to a program.

This patch is meant to be small and straightforward in order to get a minimal amount of usefulness merged.

Later today I will send a second patch, which is larger and implements the rest of the functions. If this first one isn't going to be accepted, please save me the trouble of getting the next one sent out, as it depends on this one.

2006-12-15 Joel Schopp <jschopp@austin.ibm.com>

* spu/c99ppe.h: New file
* spu/perror.c: New file
* spu/printf.c: New file
* spu/putchar.c: New file
* spu/puts.c: New file
* spu/vprintf.c: New file
* spu/vsnprintf.c: New file
* spu/vsprintf.c: New file
* spu/Makefile.am: (printf.o putchar.o puts.o vprintf.o vsnprintf.o vsprintf.o): New targets.
* spu/Makefile.in: (printf.o putchar.o puts.o vprintf.o vsnprintf.o vsprintf.o): New targets.



------------------------------------------------------------------------


Index: src/newlib/libc/machine/spu/printf.c
===================================================================
--- /dev/null
+++ src/newlib/libc/machine/spu/printf.c
@@ -0,0 +1,54 @@
+
+#include <_ansi.h>
+#include <stdio.h>
+
+#include "c99ppe.h"
+
+#ifdef _HAVE_STDC
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+typedef struct
+{
+ char* fmt;
+ unsigned int pad0[ 3 ];
+ va_list ap;
+} c99_printf_t;
+
+#ifndef _REENT_ONLY
+
+#ifdef _HAVE_STDC
+int
+_DEFUN (printf, (fmt,ap),
+ _CONST char *fmt _AND
+ ...)
+#else
+int
+#error
+printf (fmt, va_alist)
+ char *fmt;
+ va_dcl
+#endif
+{
+ int* ret;
+ c99_printf_t args;
+ ret = (int*) &args;
+
+ args.fmt = fmt;
+#ifdef _HAVE_STDC
+ va_start (args.ap, args.fmt);
+#else
+ va_start (args.ap);
+#endif
+
+
+ /* ret = vfprintf (_stdout_r (_REENT), fmt, ap);*/
+ send_to_ppe(SPE_C99_SIGNALCODE, SPE_C99_VPRINTF, &args);
+
+ va_end (args.ap);
+ return *ret;
+}
+
+#endif /* ! _REENT_ONLY */
Index: src/newlib/libc/machine/spu/c99ppe.h
===================================================================
--- /dev/null
+++ src/newlib/libc/machine/spu/c99ppe.h
@@ -0,0 +1,117 @@
+/*
+(C) Copyright IBM Corp. 2006
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of IBM 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 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 OWNER 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.
+
+Author: Joel Schopp <jschopp@austin.ibm.com>
+*/
+
+#include <errno.h>
+#include <spu_intrinsics.h>
+
+#define SPE_C99_SIGNALCODE 0x2100
+
+#define SPE_C99_OP_SHIFT 24
+#define SPE_C99_OP_MASK 0xff
+#define SPE_C99_DATA_MASK 0xffffff
+
+enum {
+ SPE_C99_CLEARERR=0x01,
+ SPE_C99_FCLOSE,
+ SPE_C99_FEOF,
+ SPE_C99_FERROR,
+ SPE_C99_FFLUSH,
+ SPE_C99_FGETC,
+ SPE_C99_FGETPOS,
+ SPE_C99_FGETS,
+ SPE_C99_FILENO,
+ SPE_C99_FOPEN, //implemented
+ SPE_C99_FPUTC,
+ SPE_C99_FPUTS,
+ SPE_C99_FREAD,
+ SPE_C99_FREOPEN,
+ SPE_C99_FSEEK,
+ SPE_C99_FSETPOS,
+ SPE_C99_FTELL,
+ SPE_C99_FWRITE,
+ SPE_C99_GETC,
+ SPE_C99_GETCHAR,
+ SPE_C99_GETS,
+ SPE_C99_PERROR,
+ SPE_C99_PUTC,
+ SPE_C99_PUTCHAR,
+ SPE_C99_PUTS,
+ SPE_C99_REMOVE,
+ SPE_C99_RENAME,
+ SPE_C99_REWIND,
+ SPE_C99_SETBUF,
+ SPE_C99_SETVBUF,
+ SPE_C99_SYSTEM, //not yet implemented in newlib
+ SPE_C99_TMPFILE,
+ SPE_C99_TMPNAM,
+ SPE_C99_UNGETC,
+ SPE_C99_VFPRINTF,
+ SPE_C99_VFSCANF,
+ SPE_C99_VPRINTF,
+ SPE_C99_VSCANF,
+ SPE_C99_VSNPRINTF,
+ SPE_C99_VSPRINTF,
+ SPE_C99_VSSCANF,
+ SPE_C99_LAST_OPCODE,
+};
+#define SPE_C99_NR_OPCODES ((SPE_C99_LAST_OPCODE - SPE_C99_CLEARERR) + 1)
+
+#define SPE_STDIN 1
+#define SPE_STDOUT 2
+#define SPE_STDERR 3
+#define SPE_FOPEN_MAX (FOPEN_MAX+1)
+#define SPE_FOPEN_MIN 4
+
+struct spe_reg128{
+ unsigned int slot[4];
+};
+
+static void
+send_to_ppe(int signalcode, int opcode, void *data)
+{
+
+ unsigned int combined = ( ( opcode<<24 )&0xff000000 ) | ( ( unsigned int )data & 0x00ffffff );
+ struct spe_reg128* ret = data;
+
+ vector unsigned int stopfunc = {
+ signalcode, /* stop 0x210x*/
+ (unsigned int) combined,
+ 0x4020007f, /* nop */
+ 0x35000000 /* bi $0 */
+ };
+
+ void (*f) (void) = (void *) &stopfunc;
+ asm ("sync":::"memory");
+ f();
+ errno = ret->slot[3];
+ return;
+}
Index: src/newlib/libc/machine/spu/perror.c
===================================================================
--- /dev/null
+++ src/newlib/libc/machine/spu/perror.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+#include "c99ppe.h"
+
+void
+_DEFUN (perror, (s),
+ _CONST char *s)
+
+{
+ send_to_ppe(SPE_C99_SIGNALCODE, SPE_C99_PERROR, &s);
+
+ return;
+}
+
Index: src/newlib/libc/machine/spu/putchar.c
===================================================================
--- /dev/null
+++ src/newlib/libc/machine/spu/putchar.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+#include "c99ppe.h"
+
+#undef putchar
+
+int
+putchar (c)
+ int c;
+{
+ /* c gets overwritten before return */
+
+ send_to_ppe(SPE_C99_SIGNALCODE, SPE_C99_PUTCHAR, &c);
+
+ return c;
+}
+
Index: src/newlib/libc/machine/spu/puts.c
===================================================================
--- /dev/null
+++ src/newlib/libc/machine/spu/puts.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+#include "c99ppe.h"
+
+int
+_DEFUN (puts, (s),
+ char _CONST * s)
+{
+
+ /* The return value gets written over s
+ */
+ send_to_ppe(SPE_C99_SIGNALCODE, SPE_C99_PUTS, &s);
+
+ return (int)s;
+}
+
Index: src/newlib/libc/machine/spu/vsnprintf.c
===================================================================
--- /dev/null
+++ src/newlib/libc/machine/spu/vsnprintf.c
@@ -0,0 +1,47 @@
+
+#include <_ansi.h>
+#include <stdio.h>
+
+#include "c99ppe.h"
+
+#ifdef _HAVE_STDC
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+typedef struct
+{
+ char* str;
+ unsigned int pad0[ 3 ];
+ size_t size;
+ unsigned int pad1[ 3 ];
+ char* fmt;
+ unsigned int pad2[ 3 ];
+ va_list ap;
+} c99_vsnprintf_t;
+
+#ifndef _REENT_ONLY
+
+int
+_DEFUN (vsnprintf, (str, size, fmt, ap),
+ char *str _AND
+ size_t size _AND
+ _CONST char *fmt _AND
+ va_list ap)
+{
+ int* ret;
+ c99_vsnprintf_t args;
+ ret = (int*) &args;
+
+ args.str = str;
+ args.size = size;
+ args.fmt = fmt;
+ va_copy(args.ap,ap);
+
+ send_to_ppe(SPE_C99_SIGNALCODE, SPE_C99_VSNPRINTF, &args);
+
+ return *ret;
+}
+
+#endif /* ! _REENT_ONLY */
Index: src/newlib/libc/machine/spu/vprintf.c
===================================================================
--- /dev/null
+++ src/newlib/libc/machine/spu/vprintf.c
@@ -0,0 +1,39 @@
+
+#include <_ansi.h>
+#include <stdio.h>
+
+#include "c99ppe.h"
+
+#ifdef _HAVE_STDC
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+typedef struct
+{
+ char* fmt;
+ unsigned int pad0[ 3 ];
+ va_list ap;
+} c99_vprintf_t;
+
+#ifndef _REENT_ONLY
+
+int
+_DEFUN (vprintf, (fmt, ap),
+ _CONST char *fmt _AND
+ va_list ap)
+{
+ int* ret;
+ c99_vprintf_t args;
+ ret = (int*) &args;
+
+ args.fmt = (char*) fmt;
+ va_copy(args.ap,ap);
+
+ send_to_ppe(SPE_C99_SIGNALCODE, SPE_C99_VPRINTF, &args);
+
+ return *ret;
+}
+
+#endif /* ! _REENT_ONLY */
Index: src/newlib/libc/machine/spu/vsprintf.c
===================================================================
--- /dev/null
+++ src/newlib/libc/machine/spu/vsprintf.c
@@ -0,0 +1,39 @@
+
+#include <_ansi.h>
+#include <stdio.h>
+
+#include "c99ppe.h"
+
+#ifdef _HAVE_STDC
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+typedef struct
+{
+ char *str;
+ unsigned int pad0[ 3 ];
+ char *fmt;
+ unsigned int pad1[ 3 ];
+ va_list ap;
+} c99_vsprintf_t;
+
+int
+_DEFUN (vsprintf, (str, fmt, ap),
+ char *str _AND
+ _CONST char *fmt _AND
+ va_list ap)
+{
+ int* ret;
+ c99_vsprintf_t args;
+ ret = (int*) &args;
+
+ args.str = str;
+ args.fmt = (char*) fmt;
+ va_copy(args.ap,ap);
+
+ send_to_ppe(SPE_C99_SIGNALCODE, SPE_C99_VSPRINTF, &args);
+
+ return *ret;
+}
Index: src/newlib/libc/machine/spu/Makefile.am
===================================================================
--- src.orig/newlib/libc/machine/spu/Makefile.am
+++ src/newlib/libc/machine/spu/Makefile.am
@@ -8,7 +8,7 @@ noinst_LIBRARIES = lib.a
AM_CCASFLAGS = $(INCLUDES)
-lib_a_SOURCES = setjmp.S memcpy.c memmove.c memset.c strcat.c strchr.c strcmp.c strcpy.c strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c strrchr.c strspn.c strxfrm.c
+lib_a_SOURCES = setjmp.S memcpy.c memmove.c memset.c strcat.c strchr.c strcmp.c strcpy.c strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c strrchr.c strspn.c strxfrm.c printf.c perror.c putchar.c puts.c vsnprintf.c vprintf.c vsprintf.c
lib_a_CCASFLAGS = $(AM_CCASFLAGS)
lib_a_CFLAGS = $(AM_CFLAGS)
Index: src/newlib/libc/machine/spu/Makefile.in
===================================================================
--- src.orig/newlib/libc/machine/spu/Makefile.in
+++ src/newlib/libc/machine/spu/Makefile.in
@@ -49,7 +49,11 @@ DIST_COMMON = $(srcdir)/../../../../conf
$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
$(srcdir)/../../../../compile $(srcdir)/../../../../compile \
- $(srcdir)/../../../../compile $(srcdir)/../../../../compile
+ $(srcdir)/../../../../compile $(srcdir)/../../../../compile \
+ $(srcdir)/../../../../compile $(srcdir)/../../../../compile \
+ $(srcdir)/../../../../compile $(srcdir)/../../../../compile \
+ $(srcdir)/../../../../compile $(srcdir)/../../../../compile \
+ $(srcdir)/../../../../compile
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../../../acinclude.m4 \
@@ -72,7 +76,10 @@ am_lib_a_OBJECTS = lib_a-setjmp.$(OBJEXT
lib_a-strncat.$(OBJEXT) lib_a-strncmp.$(OBJEXT) \
lib_a-strncpy.$(OBJEXT) lib_a-strpbrk.$(OBJEXT) \
lib_a-strrchr.$(OBJEXT) lib_a-strspn.$(OBJEXT) \
- lib_a-strxfrm.$(OBJEXT)
+ lib_a-strxfrm.$(OBJEXT) lib_a-printf.$(OBJEXT) \
+ lib_a-perror.$(OBJEXT) lib_a-putchar.$(OBJEXT) \
+ lib_a-puts.$(OBJEXT) lib_a-vsnprintf.$(OBJEXT) \
+ lib_a-vprintf.$(OBJEXT) lib_a-vsprintf.$(OBJEXT)
lib_a_OBJECTS = $(am_lib_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir)
depcomp =
@@ -197,7 +204,7 @@ AUTOMAKE_OPTIONS = cygnus
INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
noinst_LIBRARIES = lib.a
AM_CCASFLAGS = $(INCLUDES)
-lib_a_SOURCES = setjmp.S memcpy.c memmove.c memset.c strcat.c strchr.c strcmp.c strcpy.c strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c strrchr.c strspn.c strxfrm.c
+lib_a_SOURCES = setjmp.S memcpy.c memmove.c memset.c strcat.c strchr.c strcmp.c strcpy.c strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c strrchr.c strspn.c strxfrm.c printf.c perror.c putchar.c puts.c vsnprintf.c vprintf.c vsprintf.c
lib_a_CCASFLAGS = $(AM_CCASFLAGS)
lib_a_CFLAGS = $(AM_CFLAGS)
ACLOCAL_AMFLAGS = -I ../../.. @@ -367,6 +374,48 @@ lib_a-strxfrm.o: strxfrm.c
lib_a-strxfrm.obj: strxfrm.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strxfrm.obj `if test -f 'strxfrm.c'; then $(CYGPATH_W) 'strxfrm.c'; else $(CYGPATH_W) '$(srcdir)/strxfrm.c'; fi`
+
+lib_a-printf.o: printf.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-printf.o `test -f 'printf.c' || echo '$(srcdir)/'`printf.c
+
+lib_a-printf.obj: printf.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-printf.obj `if test -f 'printf.c'; then $(CYGPATH_W) 'printf.c'; else $(CYGPATH_W) '$(srcdir)/printf.c'; fi`
+
+lib_a-perror.o: perror.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-perror.o `test -f 'perror.c' || echo '$(srcdir)/'`perror.c
+
+lib_a-perror.obj: perror.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-perror.obj `if test -f 'perror.c'; then $(CYGPATH_W) 'perror.c'; else $(CYGPATH_W) '$(srcdir)/perror.c'; fi`
+
+lib_a-putchar.o: putchar.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-putchar.o `test -f 'putchar.c' || echo '$(srcdir)/'`putchar.c
+
+lib_a-putchar.obj: putchar.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-putchar.obj `if test -f 'putchar.c'; then $(CYGPATH_W) 'putchar.c'; else $(CYGPATH_W) '$(srcdir)/putchar.c'; fi`
+
+lib_a-puts.o: puts.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-puts.o `test -f 'puts.c' || echo '$(srcdir)/'`puts.c
+
+lib_a-puts.obj: puts.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-puts.obj `if test -f 'puts.c'; then $(CYGPATH_W) 'puts.c'; else $(CYGPATH_W) '$(srcdir)/puts.c'; fi`
+
+lib_a-vsnprintf.o: vsnprintf.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-vsnprintf.o `test -f 'vsnprintf.c' || echo '$(srcdir)/'`vsnprintf.c
+
+lib_a-vsnprintf.obj: vsnprintf.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-vsnprintf.obj `if test -f 'vsnprintf.c'; then $(CYGPATH_W) 'vsnprintf.c'; else $(CYGPATH_W) '$(srcdir)/vsnprintf.c'; fi`
+
+lib_a-vprintf.o: vprintf.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-vprintf.o `test -f 'vprintf.c' || echo '$(srcdir)/'`vprintf.c
+
+lib_a-vprintf.obj: vprintf.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-vprintf.obj `if test -f 'vprintf.c'; then $(CYGPATH_W) 'vprintf.c'; else $(CYGPATH_W) '$(srcdir)/vprintf.c'; fi`
+
+lib_a-vsprintf.o: vsprintf.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-vsprintf.o `test -f 'vsprintf.c' || echo '$(srcdir)/'`vsprintf.c
+
+lib_a-vsprintf.obj: vsprintf.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-vsprintf.obj `if test -f 'vsprintf.c'; then $(CYGPATH_W) 'vsprintf.c'; else $(CYGPATH_W) '$(srcdir)/vsprintf.c'; fi`
uninstall-info-am:
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]