[PATCH 09/21] mips: libc: Support for vector type in printf

Aleksandar Rikalo <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
From: Jaydeep Patil <[email protected]>

Signed-off-by: Jaydeep Patil <[email protected]>
Signed-off-by: Aleksandar Rikalo <[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.25.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.