[PATCH v3 06/13] libc: mips: Support for vector type in printf
Jovan Dmitrovic <[email protected]>
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
From: Jaydeep Patil <[email protected]> --- newlib/libc/stdio/vfprintf.c | 208 ++++++++++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 2 deletions(-) diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c index feb1fab56..c4fe346db 100644 --- a/newlib/libc/stdio/vfprintf.c +++ b/newlib/libc/stdio/vfprintf.c @@ -377,7 +377,7 @@ get_arg (struct _reent *data, int n, char *fmt, #define SHORTINT 0x040 /* short integer */ #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ #define FPT 0x100 /* Floating point number */ -#ifdef _WANT_IO_C99_FORMATS +#if defined(_WANT_IO_C99_FORMATS) || defined(__mips) # define CHARINT 0x200 /* char as integer */ #else /* define as 0, to make SARG and UARG occupy fewer instructions */ # define CHARINT 0 @@ -469,6 +469,12 @@ _VFPRINTF_R (struct _reent *data, mbstate_t state; /* mbtowc calls from library must not change state */ #endif char *malloc_buf = NULL;/* handy pointer for malloced buffers */ +#ifdef __mips + int vec_size = 2; /* 1 -> 64bits, 2 -> 128bits, 3 -> 256bits, ... */ + int elem_num = 0, elem_size = 32; + int processing_vec_type = 0; + int vec_spec = -1; /* format specifier w, W or y */ +#endif /* * Choose PADSIZE to trade efficiency vs. size. If larger printf @@ -594,6 +600,61 @@ _VFPRINTF_R (struct _reent *data, (u_long)GET_ARG (N, ap, u_int)) #endif +#ifdef __mips +quad_t vec_sarg (void) +{ + quad_t val; + + if (flags & QUADINT) + val = va_arg (ap, quad_t); + else if (flags & LONGINT) + val = va_arg (ap, long); + else if (flags & SHORTINT) + { + val = (quad_t) (short) *((short*)ap); + ap = (va_list) ((short*)ap + 1); + } + else if (flags & CHARINT) + val = (quad_t)(signed char) (*((signed char*)ap++)); + else + val = (quad_t) va_arg (ap, int); + +#ifndef _NO_LONGLONG + if ((quad_t)val < 0) +#else + if ((long) val < 0) +#endif + { + val = -val; + sign = '-'; + } + + return val; +} + +u_quad_t vec_uarg (void) +{ + u_quad_t val; + + if (flags & QUADINT) + return va_arg (ap, u_quad_t); + else if (flags & LONGINT) + return va_arg (ap, unsigned long); + else if (flags & SHORTINT) + { + val = (u_quad_t) (unsigned short) *((unsigned short*)ap); + ap = (va_list) ((unsigned short*)ap + 1); + } + else if (flags & CHARINT) + val = (u_quad_t)(unsigned char) (*((unsigned char*)ap++)); + else + val = (u_quad_t) va_arg (ap, unsigned int); + + return val; +} + +#endif /* __mips */ + #ifndef STRING_ONLY /* Initialize std streams if not dealing with sprintf family. */ CHECK_INIT (data, fp); @@ -844,6 +905,14 @@ reswitch: switch (ch) { goto error; } #endif /* !_NO_POS_ARGS */ + +#ifdef __mips + if (ch == 'w' || ch == 'W' || ch == 'y') { + vec_size = n; + goto reswitch; + } +#endif + width = n; goto reswitch; #ifdef FLOATING_POINT @@ -852,7 +921,7 @@ reswitch: switch (ch) { goto rflag; #endif case 'h': -#ifdef _WANT_IO_C99_FORMATS +#if defined(_WANT_IO_C99_FORMATS) || defined(__mips) if (*fmt == 'h') { fmt++; flags |= CHARINT; @@ -970,6 +1039,10 @@ reswitch: switch (ch) { _fpvalue = GET_ARG (N, ap, double); } +#ifdef __mips +float_number: +#endif + /* do this before tricky precision changes If the output is infinite or NaN, leading @@ -1007,6 +1080,10 @@ reswitch: switch (ch) { _fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double); } +#ifdef __mips +float_number: +#endif + /* do this before tricky precision changes */ expt = _ldcheck (&_fpvalue); if (expt == 2) { @@ -1318,6 +1395,13 @@ number: if ((dprec = prec) >= 0) * -- ANSI X3J11 */ cp = buf + BUF; + +#ifdef __mips + /* separate vector elements by space */ + if (processing_vec_type == 1 && elem_num >= 2) + *--cp = ' '; +#endif + if (_uquad != 0 || prec != 0) { /* * Unsigned mod is hard, and unsigned mod @@ -1398,6 +1482,119 @@ number: if ((dprec = prec) >= 0) size = buf + BUF - cp; skipsize: break; + +#ifdef __mips +#define MIPS_VEC_ALIGNMENT 16 + + case 'y': + case 'w': + case 'W': + + /* preserve the format specifier */ + if (vec_spec == -1) + vec_spec = ch; + + /* align the ap to fetch vector data type */ + ap = (va_list) (((size_t) ap) + (MIPS_VEC_ALIGNMENT - 1) & -MIPS_VEC_ALIGNMENT); + + base = DEC; + if (flags & ALT) + { + if (ch == 'W') + xdigs = "0123456789ABCDEF"; + else + xdigs = "0123456789abcdef"; + base = HEX; + } + + /* find size of each element and number of such elements */ + if ((flags & QUADINT) || (flags & LONGDBL)) + { + elem_size = 64; + elem_num = (32 << vec_size) / 64; + } + else if (flags & LONGINT) + { + elem_size = 32; + elem_num = (32 << vec_size) / 32; + } + else if (flags & SHORTINT) + { + elem_size = 16; + elem_num = (32 << vec_size) / 16; + } + else if (flags & CHARINT) + { + elem_size = 8; + elem_num = (32 << vec_size) / 8; + } + else + { + elem_size = 32; + elem_num = (32 << vec_size) / 32; + } + + /* start the processing of vector data types */ + processing_vec_type = 1; + + /* main loop which prints elements in the vector */ +mips_print_vec: + /* stop if we have processed elem_num */ + if (elem_num <= 0) + { + processing_vec_type = 0; /* end of vector data processing */ + vec_spec = -1; + flags &= ~FPT; + break; + } + +#ifdef FLOATING_POINT + if (vec_spec == 'y') + { + ch = 'f'; + + if (flags & LONGDBL) + _fpvalue = (double) GET_ARG (N, ap, double); + else + { + _fpvalue = (double) (float)(*(float*)ap); + ap = (va_list) ((float*)ap + 1); + } + + goto float_number; + } + else +#endif + { + if (vec_spec == 'W') + _uquad = vec_uarg (); /* unsigned */ + else + _uquad = vec_sarg (); /* signed */ + + goto number; /* process as if it is a normal number */ + } + + /* back from printing a number */ +mips_print_vec_check: + + /* print space after a floating point number */ + if (vec_spec == 'y' && elem_num >= 2) + PRINT (" ", 1); + + elem_num--; + cp = buf + BUF; /* clear the output buffer */ + size = 0; + dprec = 0; + sign = '\0'; +#ifdef FLOATING_POINT + lead = 0; +#endif + prec = -1; + goto mips_print_vec; /* loop back */ + + break; +#endif /* __mips */ + default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; @@ -1526,6 +1723,13 @@ number: if ((dprec = prec) >= 0) _free_r (data, malloc_buf); malloc_buf = NULL; } + +#ifdef __mips + /* loop back to check if there are more elements to process */ + if (processing_vec_type == 1) + goto mips_print_vec_check; +#endif + } done: FLUSH (); -- 2.34.1