From 505ccc75c4d380084ef11bc51b8d876ba656e729 Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Mon, 18 Dec 2006 20:39:02 +0000 Subject: [PATCH] 2006-12-18 Joel Schopp * libc/machine/spu/c99ppe.h: New file * libc/machine/spu/perror.c: New file to override libc/stdio version. * libc/machine/spu/printf.c: New file * libc/machine/spu/putchar.c: New file * libc/machine/spu/puts.c: New file * libc/machine/spu/vprintf.c: New file * libc/machine/spu/vsnprintf.c: New file * libc/machine/spu/vsprintf.c: New file * libc/machine/spu/Makefile.am: Add new targets. * libc/machine/spu/Makefile.in: Regenerated. --- newlib/ChangeLog | 13 ++++ newlib/libc/machine/spu/Makefile.am | 2 +- newlib/libc/machine/spu/Makefile.in | 55 ++++++++++++- newlib/libc/machine/spu/c99ppe.h | 117 ++++++++++++++++++++++++++++ newlib/libc/machine/spu/perror.c | 14 ++++ newlib/libc/machine/spu/printf.c | 54 +++++++++++++ newlib/libc/machine/spu/putchar.c | 17 ++++ newlib/libc/machine/spu/puts.c | 16 ++++ newlib/libc/machine/spu/vprintf.c | 39 ++++++++++ newlib/libc/machine/spu/vsnprintf.c | 47 +++++++++++ newlib/libc/machine/spu/vsprintf.c | 39 ++++++++++ 11 files changed, 409 insertions(+), 4 deletions(-) create mode 100644 newlib/libc/machine/spu/c99ppe.h create mode 100644 newlib/libc/machine/spu/perror.c create mode 100644 newlib/libc/machine/spu/printf.c create mode 100644 newlib/libc/machine/spu/putchar.c create mode 100644 newlib/libc/machine/spu/puts.c create mode 100644 newlib/libc/machine/spu/vprintf.c create mode 100644 newlib/libc/machine/spu/vsnprintf.c create mode 100644 newlib/libc/machine/spu/vsprintf.c diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 274e25eac..64da20e11 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,16 @@ +2006-12-18 Joel Schopp + + * libc/machine/spu/c99ppe.h: New file + * libc/machine/spu/perror.c: New file to override libc/stdio version. + * libc/machine/spu/printf.c: New file + * libc/machine/spu/putchar.c: New file + * libc/machine/spu/puts.c: New file + * libc/machine/spu/vprintf.c: New file + * libc/machine/spu/vsnprintf.c: New file + * libc/machine/spu/vsprintf.c: New file + * libc/machine/spu/Makefile.am: Add new targets. + * libc/machine/spu/Makefile.in: Regenerated. + 2006-12-18 Jeff Johnston * aclocal.m4 */aclocal.m4: Regenerated using aclocal 1.9.6. diff --git a/newlib/libc/machine/spu/Makefile.am b/newlib/libc/machine/spu/Makefile.am index e825b4203..7e24b704d 100644 --- a/newlib/libc/machine/spu/Makefile.am +++ b/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) diff --git a/newlib/libc/machine/spu/Makefile.in b/newlib/libc/machine/spu/Makefile.in index d73e7bf7d..bdacd8787 100644 --- a/newlib/libc/machine/spu/Makefile.in +++ b/newlib/libc/machine/spu/Makefile.in @@ -47,7 +47,11 @@ DIST_COMMON = $(srcdir)/../../../../config.guess \ $(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 \ @@ -70,7 +74,10 @@ am_lib_a_OBJECTS = lib_a-setjmp.$(OBJEXT) lib_a-memcpy.$(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 = @@ -195,7 +202,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 ../../.. @@ -365,6 +372,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) diff --git a/newlib/libc/machine/spu/c99ppe.h b/newlib/libc/machine/spu/c99ppe.h new file mode 100644 index 000000000..a4199bcbf --- /dev/null +++ b/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 +*/ + +#include +#include + +#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; +} diff --git a/newlib/libc/machine/spu/perror.c b/newlib/libc/machine/spu/perror.c new file mode 100644 index 000000000..ad79a48db --- /dev/null +++ b/newlib/libc/machine/spu/perror.c @@ -0,0 +1,14 @@ +#include + +#include "c99ppe.h" + +void +_DEFUN (perror, (s), + _CONST char *s) + +{ + send_to_ppe(SPE_C99_SIGNALCODE, SPE_C99_PERROR, &s); + + return; +} + diff --git a/newlib/libc/machine/spu/printf.c b/newlib/libc/machine/spu/printf.c new file mode 100644 index 000000000..d79f35dc5 --- /dev/null +++ b/newlib/libc/machine/spu/printf.c @@ -0,0 +1,54 @@ + +#include <_ansi.h> +#include + +#include "c99ppe.h" + +#ifdef _HAVE_STDC +#include +#else +#include +#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 */ diff --git a/newlib/libc/machine/spu/putchar.c b/newlib/libc/machine/spu/putchar.c new file mode 100644 index 000000000..0b6709d7f --- /dev/null +++ b/newlib/libc/machine/spu/putchar.c @@ -0,0 +1,17 @@ +#include + +#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; +} + diff --git a/newlib/libc/machine/spu/puts.c b/newlib/libc/machine/spu/puts.c new file mode 100644 index 000000000..f060494dd --- /dev/null +++ b/newlib/libc/machine/spu/puts.c @@ -0,0 +1,16 @@ +#include + +#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; +} + diff --git a/newlib/libc/machine/spu/vprintf.c b/newlib/libc/machine/spu/vprintf.c new file mode 100644 index 000000000..26dfb84ab --- /dev/null +++ b/newlib/libc/machine/spu/vprintf.c @@ -0,0 +1,39 @@ + +#include <_ansi.h> +#include + +#include "c99ppe.h" + +#ifdef _HAVE_STDC +#include +#else +#include +#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 */ diff --git a/newlib/libc/machine/spu/vsnprintf.c b/newlib/libc/machine/spu/vsnprintf.c new file mode 100644 index 000000000..a5ed0f2ee --- /dev/null +++ b/newlib/libc/machine/spu/vsnprintf.c @@ -0,0 +1,47 @@ + +#include <_ansi.h> +#include + +#include "c99ppe.h" + +#ifdef _HAVE_STDC +#include +#else +#include +#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 */ diff --git a/newlib/libc/machine/spu/vsprintf.c b/newlib/libc/machine/spu/vsprintf.c new file mode 100644 index 000000000..3a45c2b92 --- /dev/null +++ b/newlib/libc/machine/spu/vsprintf.c @@ -0,0 +1,39 @@ + +#include <_ansi.h> +#include + +#include "c99ppe.h" + +#ifdef _HAVE_STDC +#include +#else +#include +#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; +}