[Cbe-oss-dev] [PATCH] libspe: SPE C99 handler for PowerPC64 with varargs

Kazunori Asayama asayama at sm.sony.co.jp
Mon Apr 24 20:03:45 EST 2006


This patch provides SPE C99 handler for PowerPC 64 with
variable arguments such as printf().
It should be applied to development version of libspe 1.0.1
w/ va_list alignment patch.

Thanks,
-- 
(ASAYAMA Kazunori
  (asayama at sm.sony.co.jp))
t
--
Index: libspe-1.0.1/default_c99_handler.c
===================================================================
RCS file: /cvsroot/misc/libspe/default_c99_handler.c,v
retrieving revision 1.1.1.2.4.1
diff -u -p -r1.1.1.2.4.1 default_c99_handler.c
--- libspe-1.0.1/default_c99_handler.c	21 Apr 2006 08:17:57 -0000	1.1.1.2.4.1
+++ libspe-1.0.1/default_c99_handler.c	24 Apr 2006 04:46:26 -0000
@@ -163,6 +163,15 @@ typedef unsigned long long __va_elem;
 	(__va_elem *)(((unsigned long)alloca((_nr+1) * sizeof(__va_elem) + __VA_LIST_ALIGN) \
 		       + __VA_LIST_ALIGN - 1) & ~(__VA_LIST_ALIGN - 1))

+#ifdef __powerpc64__
+#define __VA_LIST_PUT(_vargs, _type, _a)                		\
+        ((_type *) ((unsigned long) _vargs + sizeof(__va_elem) - sizeof(_type)))[0] = (_a); \
+        _vargs = (__va_elem *)_vargs + 1
+
+#define __VA_TEMP_ALLOCA(_nr) (struct __va_temp *) alloca((_nr+1) * sizeof(struct __va_temp))
+
+#else /* !__powerpc64__ */
+
 #define __OFFSET(_type)	(sizeof(_type)-1)
 #define __MASK(_type)	~(__OFFSET(_type))

@@ -178,6 +187,10 @@ typedef unsigned long long __va_elem;
         ((_type *) _vargs)[0] = (_a);                   		\
         _vargs = (__va_elem *)(((_type *) _vargs) + 1)

+#define __VA_TEMP_ALLOCA(_nr) NULL /* unused */
+
+#endif /* !__powerpc64__ */
+
 #define GET_LS_VARG(_name) {                        			  \
         memcpy(&(_name), GET_LS_PTR(spe_vlist->next_arg), sizeof(_name)); \
         spe_vlist->next_arg += 16;					  \
@@ -208,11 +221,14 @@ struct __ppc32_va_list {
     char pad[3];
     void *ptr;
 };
-#else
-#warning Missing ppc64 va_list!
-#warning Some c99 functions will not work
 #endif /* __powerpc64__ */

+/* Temporary area to save long value or pointer on ppc64. */
+struct __va_temp {
+  long long llval;
+  int *ptr;
+};
+
 /* TO-DO: update these to support 64b PPC-ABI. */
 static int __do_vfprintf(FILE * stream, char *format, __va_elem * vlist)
 {
@@ -223,7 +239,7 @@ static int __do_vfprintf(FILE * stream,
     ap.ptr = (void *) vlist;
     return vfprintf(stream, format, (void *) &ap);
 #else
-    return 0;
+    return vfprintf(stream, format, (void *) vlist);
 #endif
 }

@@ -236,7 +252,7 @@ static int __do_vsprintf(char *string, c
     ap.ptr = (void *) vlist;
     return vsprintf(string, format, (void *) &ap);
 #else
-    return 0;
+    return vsprintf(string, format, (void *) vlist);
 #endif
 }

@@ -250,7 +266,7 @@ static int __do_vsnprintf(char *string,
     ap.ptr = (void *) vlist;
     return vsnprintf(string, size, format, (void *) &ap);
 #else
-    return 0;
+    return vsnprintf(string, size, format, (void *) vlist);
 #endif
 }

@@ -263,7 +279,7 @@ static int __do_vfscanf(FILE * stream, c
     ap.ptr = (void *) vlist;
     return vfscanf(stream, format, (void *) &ap);
 #else
-    return 0;
+    return vfscanf(stream, format, (void *) vlist);
 #endif
 }

@@ -276,10 +292,22 @@ static int __do_vsscanf(char *string, ch
     ap.ptr = (void *) vlist;
     return vsscanf(string, format, (void *) &ap);
 #else
-    return 0;
+    return vsscanf(string, format, (void *) vlist);
 #endif
 }

+#ifdef __powerpc64__
+static void __copy_va_temp(struct __va_temp *vtemps)
+{
+    while (vtemps->ptr) {
+      *vtemps->ptr = vtemps->llval;
+      vtemps++;
+    }
+}
+#else /* !__powerpc64__ */
+#define __copy_va_temp(vtemps) /* do nothing */
+#endif /* __powerpc64__ */
+
 static inline FILE *get_FILE(int nr)
 {
     FILE *ret;
@@ -434,7 +462,7 @@ static inline FILE *get_FILE(int nr)
       h = 1;                                    \
       p++;                                      \
     case 'l':                                   \
-      l = 1;                                    \
+      l++;                                      \
       p++;                                      \
       break;                                    \
     case '*':                                   \
@@ -540,12 +568,28 @@ static int __parse_printf_format(char *l
 		p += 2;
 	    } else {
 		GET_LS_VARG(ival);
+#ifdef __powerpc64__
+		if (p[1] == 'd') {
+		  __VA_LIST_PUT(vlist, long, (long)ival);
+		}
+		else {
+		  __VA_LIST_PUT(vlist, unsigned long,
+				(unsigned long)(unsigned int)ival);
+		}
+#else /* !__powerpc64__*/
 		__VA_LIST_PUT(vlist, int, ival);
+#endif /* __powerpc64__*/
 		p += 1;
 	    }
 	    break;
-	case 'o':
 	case 'p':
+#ifdef __powerpc64__
+	    GET_LS_VARG(ival);
+	    __VA_LIST_PUT(vlist, unsigned long,
+			  (unsigned long)(unsigned int)ival);
+	    break;
+#endif /* __powerpc64__ */
+	case 'o':
 	case 'u':
 	case 'x':
 	case 'X':
@@ -566,7 +610,7 @@ static int __parse_printf_format(char *l

 static int __parse_scanf_format(char *ls, char *format,
 			        struct spe_va_list *spe_vlist,
-			        __va_elem * vlist, int nr_vargs)
+			        __va_elem * vlist, struct __va_temp *vtemps, int nr_vargs)
 {
     int fw;
     int format_half, format_long, suppress;
@@ -574,8 +618,12 @@ static int __parse_scanf_format(char *ls
     char *p, *pstart;
     void *ptr;

-    if (nr_vargs == 0)
+    if (nr_vargs == 0) {
+#ifdef __powerpc64__
+	vtemps->ptr = NULL;
+#endif /* __powerpc64__ */
 	return 0;
+    }

     for (p = (char *) format, pstart = (char *) format; *p;) {
 	p = strchr(p, '%');
@@ -598,12 +646,22 @@ static int __parse_scanf_format(char *ls
 		    ptr = GET_LS_PTR(ls_offset);
 		    __VA_LIST_PUT(vlist, short *, ptr);
 		}
-	    } else if (format_long) {
+	    } else if (format_long == 2) {
 		if (!suppress) {
 		    GET_LS_VARG(ls_offset);
 		    ptr = GET_LS_PTR(ls_offset);
 		    __VA_LIST_PUT(vlist, long long *, ptr);
 		}
+#ifdef __powerpc64__
+	    } else if (format_long) {
+		if (!suppress) {
+		    GET_LS_VARG(ls_offset);
+		    ptr = GET_LS_PTR(ls_offset);
+		    vtemps->ptr = ptr;
+		    __VA_LIST_PUT(vlist, long long *, &vtemps->llval);
+		    vtemps++;
+		}
+#endif /* __powerpc64__ */
 	    } else {
 		if (!suppress) {
 		    GET_LS_VARG(ls_offset);
@@ -640,7 +698,13 @@ static int __parse_scanf_format(char *ls
 	    if (!suppress) {
 		GET_LS_VARG(ls_offset);
 		ptr = GET_LS_PTR(ls_offset);
+#ifdef __powerpc64__
+		vtemps->ptr = ptr;
+		__VA_LIST_PUT(vlist, long long *, &vtemps->llval);
+		vtemps++;
+#else /* !__powerpc64__ */
 		__VA_LIST_PUT(vlist, unsigned long *, ptr);
+#endif /* !__powerpc64__ */
 	    }
 	    break;
 	case 'c':
@@ -671,6 +735,9 @@ static int __parse_scanf_format(char *ls
 	    break;
 	}
     }
+#ifdef __powerpc64__
+    vtemps->ptr = NULL;
+#endif /* __powerpc64__ */
     return 0;
 }

@@ -1031,6 +1098,7 @@ int default_c99_handler_vfscanf(char *ls
     int rc, nr_vargs;
     struct spe_va_list spe_vlist;
     __va_elem *vlist;
+    struct __va_temp *vtemps;

     DEBUG_PRINTF("%s\n", __func__);
     CHECK_C99_OPCODE(VFSCANF);
@@ -1039,8 +1107,15 @@ int default_c99_handler_vfscanf(char *ls
     memcpy(&spe_vlist, arg2, sizeof(struct spe_va_list));
     nr_vargs = __nr_format_args(format);
     vlist = __VA_LIST_ALLOCA(nr_vargs);
-    rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, nr_vargs);
-    rc = (rc == 0) ? __do_vfscanf(stream, format, vlist) : EOF;
+    vtemps = __VA_TEMP_ALLOCA(nr_vargs);
+    rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs);
+    if (rc == 0) {
+      rc = __do_vfscanf(stream, format, vlist);
+      __copy_va_temp(vtemps);
+    }
+    else {
+      rc = EOF;
+    }
     PUT_LS_RC(rc, 0, 0, errno);
     return 0;
 }
@@ -1097,6 +1172,7 @@ int default_c99_handler_vscanf(char *ls,
     int rc, nr_vargs;
     struct spe_va_list spe_vlist;
     __va_elem *vlist;
+    struct __va_temp *vtemps;

     DEBUG_PRINTF("%s\n", __func__);
     CHECK_C99_OPCODE(VSCANF);
@@ -1105,8 +1181,15 @@ int default_c99_handler_vscanf(char *ls,
     memcpy(&spe_vlist, arg1, sizeof(struct spe_va_list));
     nr_vargs = __nr_format_args(format);
     vlist = __VA_LIST_ALLOCA(nr_vargs);
-    rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, nr_vargs);
-    rc = (rc == 0) ? __do_vfscanf(stream, format, vlist) : EOF;
+    vtemps = __VA_TEMP_ALLOCA(nr_vargs);
+    rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs);
+    if (rc == 0) {
+      rc = __do_vfscanf(stream, format, vlist);
+      __copy_va_temp(vtemps);
+    }
+    else {
+      rc = EOF;
+    }
     PUT_LS_RC(rc, 0, 0, errno);
     return 0;
 }
@@ -1198,6 +1281,7 @@ int default_c99_handler_vsscanf(char *ls
     int rc, nr_vargs;
     struct spe_va_list spe_vlist;
     __va_elem *vlist;
+    struct __va_temp *vtemps;

     DEBUG_PRINTF("%s\n", __func__);
     CHECK_C99_OPCODE(VSSCANF);
@@ -1206,8 +1290,15 @@ int default_c99_handler_vsscanf(char *ls
     memcpy(&spe_vlist, arg2, sizeof(struct spe_va_list));
     nr_vargs = __nr_format_args(format);
     vlist = __VA_LIST_ALLOCA(nr_vargs);
-    rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, nr_vargs);
-    rc = (rc == 0) ? __do_vsscanf(str, format, vlist) : EOF;
+    vtemps = __VA_TEMP_ALLOCA(nr_vargs);
+    rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs);
+    if (rc == 0) {
+      rc = __do_vsscanf(str, format, vlist);
+      __copy_va_temp(vtemps);
+    }
+    else {
+      rc = EOF;
+    }
     PUT_LS_RC(rc, 0, 0, errno);
     return 0;
 }



More information about the cbe-oss-dev mailing list