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