non-FP tasks
Kate Feng
feng1 at bnl.gov
Tue Jun 19 12:10:02 UTC 2007
Till Straumann wrote:
> For a long time I have been patching newlib
> so that it dynamically switches to vfiprintf
> when executed by a non-FP task.
>
> The patch also addresses setjmp/longjmp
> (only saves/restores FP regs for FP tasks).
>
> Finally, the patch also addresses altivec.
>
> However: the patch addresses PPC only ATM.
>
> HTH
> -- Till
>
> PS: originally created for newlib-1.13 but I
> have used it on later versions, too.
I used newlib-1.15.0 and gcc-4.1.1.
In newlib/libc/machine/powerpc/configure :
case $host in
+ powerpc*-*rtems*)
+ extra_objs="vfprintf.o vfscanf.o"
+ extra_sources="vfprintf.c vfscanf.c"
I am not sure about the '$host', which I thought should be
'$target'. However,
it seems that the patch was built under the target of
my system ( -mcpu=7450) at :
gcc-4.1.1/build/ppc-rtems/m7400/newlib/libc/machine/powerpc/vfprintf.o
However, it does not seem to be built into the RTEMS image if it's
linked with cexp, when I examined the object code. Perhaps, was it
overwitten by the library of the cexp ? Is a patch needed for
cexp as well ? Or something elase ?
Thanks,
Kate
>
>
> Kate Feng wrote:
> > rtems_bsdnet_newproc() generated tasks are non-FP. However,
> >
> > 1) The networkDaemon in cpukit/libnetworking/rtems calls
> > 'sprintf' for arpint, which eventually will cause FP unavailable
> > exception if network driver are built with -msoft-float.
> > Suggestion ?
> >
> > 2) Network drivers use printk, rtems_panic, and printf,
> > which are all currently compiled using the FP registers
> > under all 4.6 and 4.7. How about having printk compiled
> > with -msoft-float since it could be called from ISR ?
> > Can this be implemented in 4.7.x ?
> >
> > Regards,
> > Kate
> >
> >
> >
> > _______________________________________________
> > rtems-users mailing list
> > rtems-users at rtems.com
> > http://rtems.rtems.org/mailman/listinfo/rtems-users
> >
>
> ------------------------------------------------------------------------
> Patch against newlib-1.13.0.
>
> This patch provides the following features:
> - let powerpc*-*rtems* targets use powerpc/altivec specific vfprintf/vfscanf implementations.
> - enable altivec printf/scanf formats even when not compiled -maltivec. I.e., non-altivec
> enabled tasks are guaranteed to not incur an 'altivec not available' exception while
> printing vectors from altivec-enabled tasks still works. (Vector data in memory can also
> be printed/scanned by non-vector tasks.)
> - vfprintf() dynamically switches to vfiprintf() when called from a non-FP task (so that
> an integer-only task doesn't implicitely use FP registers).
> - setjmp/longjmp save/restore FP and altivec registers only when called from an appropriate
> task context. (e.g., an integer-only, altivec-enabled task saves/restores only GPRs and VRs.)
>
> Author: Till Straumann <strauman at slac.stanford.edu>, 2005
>
> To apply this patch, chdir to the newlib-1.13.0 source topdir and issue
>
> patch -p1 < <this_file>
>
> Note that it is always a good idea to try a --dry-run first. YMMV
>
> *** newlib-1.13.0/newlib/libc/machine/powerpc/configure.in.orig 2005-11-18 21:30:20.000000000 -0800
> --- newlib-1.13.0/newlib/libc/machine/powerpc/configure.in 2005-11-18 22:04:32.000000000 -0800
> ***************
> *** 12,17 ****
> --- 12,21 ----
> extra_objs=
> extra_sources=
> case $host in
> + powerpc*-*rtems*)
> + extra_objs="vfprintf.o vfscanf.o"
> + extra_sources="vfprintf.c vfscanf.c"
> + ;;
> powerpc*-*altivec*)
> extra_objs="vfprintf.o vfscanf.o vec_malloc.o vec_calloc.o vec_free.o vec_realloc.o vec_reallocr.o vec_callocr.o"
> extra_sources="vfprintf.c vfscanf.c vec_malloc.c vec_calloc.c vec_free.c vec_realloc.c vec_mallocr.c"
> *** newlib-1.13.0/newlib/libc/machine/powerpc/configure.orig 2005-11-18 21:32:08.000000000 -0800
> --- newlib-1.13.0/newlib/libc/machine/powerpc/configure 2005-11-18 22:04:43.000000000 -0800
> ***************
> *** 1568,1573 ****
> --- 1568,1577 ----
> extra_objs=
> extra_sources=
> case $host in
> + powerpc*-*rtems*)
> + extra_objs="vfprintf.o vfscanf.o"
> + extra_sources="vfprintf.c vfscanf.c"
> + ;;
> powerpc*-*altivec*)
> extra_objs="vfprintf.o vfscanf.o vec_malloc.o vec_calloc.o vec_free.o vec_realloc.o vec_reallocr.o vec_callocr.o"
> extra_sources="vfprintf.c vfscanf.c vec_malloc.c vec_calloc.c vec_free.c vec_realloc.c vec_mallocr.c"
> *** newlib-1.13.0/newlib/libc/machine/powerpc/setjmp.S.orig 2002-04-19 12:16:17.000000000 -0700
> --- newlib-1.13.0/newlib/libc/machine/powerpc/setjmp.S 2005-11-18 20:53:39.000000000 -0800
> ***************
> *** 5,17 ****
> --- 5,30 ----
> #include "ppc-asm.h"
>
> FUNC_START(setjmp)
> + #ifdef __rtems__
> + mfmsr 4
> + rlwinm. 4,4,0,6,6 # check MSR_VE
> + addi 3,3,7
> + rlwinm 3,3,0,0,28 # align to 8 byte boundary
> + beq 1f
> + addi 3,3,15 # VE is enabled; align to 16 byte bdry
> + rlwinm 3,3,0,0,27
> + 1:
> + #else /* defined __rtems__ */
> #ifdef __ALTIVEC__
> + mfmsr 4
> + rlwinm. 4,4,0,6,6 # check MSR_VE
> addi 3,3,15 # align Altivec to 16 byte boundary
> rlwinm 3,3,0,0,27
> #else
> addi 3,3,7 # align to 8 byte boundary
> rlwinm 3,3,0,0,28
> #endif
> + #endif /* defined __rtems__ */
> stw 1,0(3) # offset 0
> stwu 2,4(3) # offset 4
> stwu 13,4(3) # offset 8
> ***************
> *** 39,44 ****
> --- 52,65 ----
> stwu 4,4(3) # offset 88
> # one word pad to get floating point aligned on 8 byte boundary
> #ifndef _SOFT_FLOAT
> + #ifdef __rtems__
> + mfmsr 4
> + rlwinm. 4,4,0,18,18
> + bne 1f # only save FPregs if FPU is enabled
> + addi 3,3,18*8 # skip FPregs
> + b 2f
> + 1:
> + #endif
> stfdu 14,8(3) # offset 96
> stfdu 15,8(3) # offset 104
> stfdu 16,8(3) # offset 112
> ***************
> *** 57,68 ****
> stfdu 29,8(3) # offset 216
> stfdu 30,8(3) # offset 224
> stfdu 31,8(3) # offset 232
> #endif
>
> /* This requires a total of 21 * 4 + 18 * 8 + 4 + 4 + 4
> bytes == 60 * 4 bytes == 240 bytes. */
>
> ! #ifdef __ALTIVEC__
> /* save Altivec vrsave and vr20-vr31 registers */
> mfspr 4,256 # vrsave register
> stwu 4,16(3) # offset 248
> --- 78,101 ----
> stfdu 29,8(3) # offset 216
> stfdu 30,8(3) # offset 224
> stfdu 31,8(3) # offset 232
> + #ifdef __rtems__
> + 2:
> + #endif
> #endif
>
> /* This requires a total of 21 * 4 + 18 * 8 + 4 + 4 + 4
> bytes == 60 * 4 bytes == 240 bytes. */
>
> ! #if defined(__ALTIVEC__) || defined(__rtems__)
> ! #ifdef __rtems__
> ! /* could reuse r4 but I reload it just in case the code changes... */
> ! mfmsr 4
> ! rlwinm. 4,4,0,6,6 # check MSR_VE
> ! bne 1f # only save vector regs if altivec is enabled
> ! addi 3,3,(8 + 12*16) # skip vector regs
> ! b 2f
> ! 1:
> ! #endif
> /* save Altivec vrsave and vr20-vr31 registers */
> mfspr 4,256 # vrsave register
> stwu 4,16(3) # offset 248
> ***************
> *** 90,95 ****
> --- 123,131 ----
> stvx 30,0,3 # offset 416
> addi 3,3,16
> stvx 31,0,3 # offset 432
> + #ifdef __rtems__
> + 2:
> + #endif
>
> /* This requires a total of 240 + 8 + 8 + 12 * 16 == 448 bytes. */
> #endif
> ***************
> *** 99,104 ****
> --- 135,150 ----
>
>
> FUNC_START(longjmp)
> + #ifdef __rtems__
> + mfmsr 4
> + rlwinm. 4,4,0,6,6 # check MSR_VE
> + addi 3,3,7
> + rlwinm 3,3,0,0,28 # align to 8 byte boundary
> + beq 1f
> + addi 3,3,15 # VE is enabled; align to 16 byte bdry
> + rlwinm 3,3,0,0,27
> + 1:
> + #else /* defined __rtems__ */
> #ifdef __ALTIVEC__
> addi 3,3,15 # align Altivec to 16 byte boundary
> rlwinm 3,3,0,0,27
> ***************
> *** 106,111 ****
> --- 152,158 ----
> addi 3,3,7 # align to 8 byte boundary
> rlwinm 3,3,0,0,28
> #endif
> + #endif /* defined __rtems__ */
> lwz 1,0(3) # offset 0
> lwzu 2,4(3) # offset 4
> lwzu 13,4(3) # offset 8
> ***************
> *** 129,138 ****
> lwzu 31,4(3) # offset 80
> lwzu 5,4(3) # offset 84
> mtlr 5
> lwzu 5,4(3) # offset 88
> - mtcrf 255,5
> # one word pad to get floating point aligned on 8 byte boundary
> #ifndef _SOFT_FLOAT
> lfdu 14,8(3) # offset 96
> lfdu 15,8(3) # offset 104
> lfdu 16,8(3) # offset 112
> --- 176,194 ----
> lwzu 31,4(3) # offset 80
> lwzu 5,4(3) # offset 84
> mtlr 5
> + #if !defined(_SOFT_FLOAT) && defined(__rtems__)
> + mfmsr 5
> + rlwinm. 5,5,0,18,18 # is MSR_FP set?
> + #endif
> lwzu 5,4(3) # offset 88
> # one word pad to get floating point aligned on 8 byte boundary
> #ifndef _SOFT_FLOAT
> + #ifdef __rtems__
> + bne 1f
> + addi 3,3,18*8 # skip FPregs
> + b 2f
> + 1:
> + #endif
> lfdu 14,8(3) # offset 96
> lfdu 15,8(3) # offset 104
> lfdu 16,8(3) # offset 112
> ***************
> *** 151,159 ****
> lfdu 29,8(3) # offset 216
> lfdu 30,8(3) # offset 224
> lfdu 31,8(3) # offset 232
> #endif
>
> ! #ifdef __ALTIVEC__
> /* restore Altivec vrsave and v20-v31 registers */
> lwzu 5,16(3) # offset 248
> mtspr 256,5 # vrsave
> --- 207,227 ----
> lfdu 29,8(3) # offset 216
> lfdu 30,8(3) # offset 224
> lfdu 31,8(3) # offset 232
> + #ifdef __rtems__
> + 2:
> + #endif
> #endif
> + mtcrf 255,5
>
> ! #if defined(__ALTIVEC__) || defined(__rtems__)
> ! #ifdef __rtems__
> ! mfmsr 5
> ! rlwinm. 5,5,0,6,6 # is MSR_FP set?
> ! bne 1f
> ! addi 3,3,(8+12*16) # skip vector regs
> ! b 2f
> ! 1:
> ! #endif
> /* restore Altivec vrsave and v20-v31 registers */
> lwzu 5,16(3) # offset 248
> mtspr 256,5 # vrsave
> ***************
> *** 181,186 ****
> --- 249,257 ----
> lvx 30,0,3 # offset 416
> addi 3,3,16
> lvx 31,0,3 # offset 432
> + #ifdef __rtems__
> + 2:
> + #endif
> #endif
>
> mr. 3,4
> *** newlib-1.13.0/newlib/libc/machine/powerpc/vfprintf.c.orig 2005-10-22 22:47:56.000000000 -0700
> --- newlib-1.13.0/newlib/libc/machine/powerpc/vfprintf.c 2005-12-07 15:23:31.000000000 -0800
> ***************
> *** 191,199 ****
> #endif
>
> #ifdef __ALTIVEC__
> typedef union
> {
> ! vector int v;
> float f[4];
> int i[16 / sizeof(int)];
> long l[4];
> --- 191,207 ----
> #endif
>
> #ifdef __ALTIVEC__
> + typedef vector int vector_int;
> + #elif defined(__rtems__)
> + typedef int vector_int[4];
> + #define __ALTIVEC__
> + #endif
> +
> +
> + #ifdef __ALTIVEC__
> typedef union
> {
> ! vector_int v;
> float f[4];
> int i[16 / sizeof(int)];
> long l[4];
> ***************
> *** 315,320 ****
> --- 323,329 ----
> #define VECTOR 0x200 /* vector */
> #define FIXEDPOINT 0x400 /* fixed-point */
>
> + #ifdef VFPRINTF
> int
> _DEFUN (VFPRINTF, (fp, fmt0, ap),
> FILE * fp _AND
> ***************
> *** 324,336 ****
> --- 333,369 ----
> CHECK_INIT (_REENT);
> return _VFPRINTF_R (_REENT, fp, fmt0, ap);
> }
> + #endif
> +
> + #if defined(__rtems__) && !defined(INTEGER_ONLY) && defined(FLOATING_POINT)
> +
> + static int
> + _vfprintf_f_r (struct _reent *, FILE *, const char *, va_list)__attribute__((noinline));
> +
> + int
> + _DEFUN (_VFPRINTF_R, (data, fp, fmt0, ap),
> + struct _reent *data _AND
> + FILE * fp _AND
> + _CONST char *fmt0 _AND
> + va_list ap)
> + {
> + unsigned msr;
> + __asm__ __volatile__("mfmsr %0":"=r"(msr));
> + if ( msr & (1<<(31-18)) )
> + return _vfprintf_f_r(data,fp,fmt0,ap);
> + return _vfiprintf_r(data, fp, fmt0, ap);
> + }
>
> + static int
> + _vfprintf_f_r (struct _reent *data, FILE *fp, const char *fmt0, va_list ap)
> + #else
> int
> _DEFUN (_VFPRINTF_R, (data, fp, fmt0, ap),
> struct _reent *data _AND
> FILE * fp _AND
> _CONST char *fmt0 _AND
> va_list ap)
> + #endif
> {
> register char *fmt; /* format string */
> register int ch; /* character from fmt */
> ***************
> *** 435,470 ****
> #define GET_SHORT(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 8 ? (short)vec_tmp.s[8 - vec_print_count] : \
> ! (vec_tmp.v = va_arg(ap, vector int), (short)vec_tmp.s[0])) : \
> (short)va_arg(ap, int))
> #define GET_USHORT(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 8 ? (u_short)vec_tmp.s[8 - vec_print_count] : \
> ! (vec_tmp.v = va_arg(ap, vector int), (u_short)vec_tmp.s[0])) : \
> (u_short)va_arg(ap, int))
>
> #define GET_LONG(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 4 ? (long)vec_tmp.l[4 - vec_print_count] : \
> ! (vec_tmp.v = va_arg(ap, vector int), vec_tmp.l[0])) : \
> va_arg(ap, long int))
> #define GET_ULONG(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 4 ? (u_long)vec_tmp.l[4 - vec_print_count] : \
> ! (vec_tmp.v = va_arg(ap, vector int), (u_long)vec_tmp.l[0])) : \
> (u_long)va_arg(ap, unsigned long int))
>
> #define GET_INT(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 16 ? \
> vec_tmp.c[16 - vec_print_count] : \
> ! (vec_tmp.v = va_arg(ap, vector int), (int)vec_tmp.c[0])) : \
> va_arg(ap, int))
> #define GET_UINT(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 16 ? \
> (u_int)((unsigned char)vec_tmp.c[16 - vec_print_count]) : \
> ! (vec_tmp.v = va_arg(ap, vector int), (u_int)((unsigned char)vec_tmp.c[0]))) : \
> (u_int)va_arg(ap, unsigned int))
> #else /* !__ALTIVEC__ */
> #define GET_SHORT(ap) ((short)va_arg(ap, int))
> --- 468,503 ----
> #define GET_SHORT(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 8 ? (short)vec_tmp.s[8 - vec_print_count] : \
> ! (vec_tmp.v = va_arg(ap, vector_int), (short)vec_tmp.s[0])) : \
> (short)va_arg(ap, int))
> #define GET_USHORT(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 8 ? (u_short)vec_tmp.s[8 - vec_print_count] : \
> ! (vec_tmp.v = va_arg(ap, vector_int), (u_short)vec_tmp.s[0])) : \
> (u_short)va_arg(ap, int))
>
> #define GET_LONG(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 4 ? (long)vec_tmp.l[4 - vec_print_count] : \
> ! (vec_tmp.v = va_arg(ap, vector_int), vec_tmp.l[0])) : \
> va_arg(ap, long int))
> #define GET_ULONG(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 4 ? (u_long)vec_tmp.l[4 - vec_print_count] : \
> ! (vec_tmp.v = va_arg(ap, vector_int), (u_long)vec_tmp.l[0])) : \
> (u_long)va_arg(ap, unsigned long int))
>
> #define GET_INT(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 16 ? \
> vec_tmp.c[16 - vec_print_count] : \
> ! (vec_tmp.v = va_arg(ap, vector_int), (int)vec_tmp.c[0])) : \
> va_arg(ap, int))
> #define GET_UINT(ap) \
> (flags&VECTOR ? \
> (vec_print_count < 16 ? \
> (u_int)((unsigned char)vec_tmp.c[16 - vec_print_count]) : \
> ! (vec_tmp.v = va_arg(ap, vector_int), (u_int)((unsigned char)vec_tmp.c[0]))) : \
> (u_int)va_arg(ap, unsigned int))
> #else /* !__ALTIVEC__ */
> #define GET_SHORT(ap) ((short)va_arg(ap, int))
> ***************
> *** 716,722 ****
> fmt = format_anchor;
> continue;
> }
> ! tmp.v = va_arg(ap, vector int);
> cp = buf;
> for (k = 0; k < 15; ++k)
> {
> --- 749,755 ----
> fmt = format_anchor;
> continue;
> }
> ! tmp.v = va_arg(ap, vector_int);
> cp = buf;
> for (k = 0; k < 15; ++k)
> {
> ***************
> *** 783,789 ****
> if (vec_print_count >= 4)
> {
> vec_print_count = 4;
> ! vec_tmp.v = va_arg(ap, vector int);
> }
> _fpvalue = (double)vec_tmp.f[4 - vec_print_count];
> } else if (vec_sep != ' ') {
> --- 816,822 ----
> if (vec_print_count >= 4)
> {
> vec_print_count = 4;
> ! vec_tmp.v = va_arg(ap, vector_int);
> }
> _fpvalue = (double)vec_tmp.f[4 - vec_print_count];
> } else if (vec_sep != ' ') {
> ***************
> *** 822,828 ****
> if (vec_print_count >= 4)
> {
> vec_print_count = 4;
> ! vec_tmp.v = va_arg(ap, vector int);
> }
> _fpvalue = (_LONG_DOUBLE)k.f[4 - vec_print_count];
> #endif /* __ALTIVEC__ */
> --- 855,861 ----
> if (vec_print_count >= 4)
> {
> vec_print_count = 4;
> ! vec_tmp.v = va_arg(ap, vector_int);
> }
> _fpvalue = (_LONG_DOUBLE)k.f[4 - vec_print_count];
> #endif /* __ALTIVEC__ */
> *** newlib-1.13.0/newlib/libc/machine/powerpc/vfscanf.c.orig 2005-11-18 21:54:02.000000000 -0800
> --- newlib-1.13.0/newlib/libc/machine/powerpc/vfscanf.c 2005-11-18 22:06:40.000000000 -0800
> ***************
> *** 249,254 ****
> --- 249,257 ----
> return __svfscanf_r (data, fp, fmt, ap);
> }
>
> + #if defined(__rtems__) && defined(FLOATING_POINT)
> + static int
> + __svfscanf_f_r (struct _reent *, FILE *, char const *, va_list)__attribute__((noinline));
>
> int
> __svfscanf_r (rptr, fp, fmt0, ap)
> ***************
> *** 257,262 ****
> --- 260,282 ----
> char _CONST *fmt0;
> va_list ap;
> {
> + unsigned msr;
> + int which;
> + __asm__ __volatile__("mfmsr %0":"=r"(msr));
> + return (msr & (1<<(31-18))) ? __svfscanf_f_r(rptr, fp, fmt0, ap) : __svfiscanf_r(rptr, fp, fmt0, ap) ;
> + }
> +
> + static int
> + __svfscanf_f_r (struct _reent *rptr, FILE *fp, char const *fmt0, va_list ap)
> + #else
> + int
> + __svfscanf_r (rptr, fp, fmt0, ap)
> + struct _reent *rptr;
> + register FILE *fp;
> + char _CONST *fmt0;
> + va_list ap;
> + #endif
> + {
> register u_char *fmt = (u_char *) fmt0;
> register int c; /* character from format, or conversion */
> register int type; /* conversion type */
> ***************
> *** 397,403 ****
> if (flags & VECTOR)
> vec_read_count = 8;
> goto again;
> ! #ifdef __ALTIVEC__
> case 'v':
> flags |= VECTOR;
> vec_read_count = (flags & SHORT) ? 8 : ((flags & LONG) ? 4 : 16);
> --- 417,423 ----
> if (flags & VECTOR)
> vec_read_count = 8;
> goto again;
> ! #if defined(__ALTIVEC__) || defined(__rtems__)
> case 'v':
> flags |= VECTOR;
> vec_read_count = (flags & SHORT) ? 8 : ((flags & LONG) ? 4 : 16);
More information about the users
mailing list