non-FP tasks
Till Straumann
strauman at slac.stanford.edu
Tue Jun 19 17:21:24 UTC 2007
Kate Feng wrote:
> 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"
>
host seems correct.
> 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
>
seems OK. Likewise, it should be built for other powerpc multitlib
variants.
> 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 ?
no
> Or something elase ?
>
Try to dump a link map and find out where the linked vfprintf.o comes from
HTH
-- Till
> 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