[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