public inbox for libffi-discuss@sourceware.org
 help / color / mirror / Atom feed
* libffi on the HPPA (parisc)
@ 2019-04-13 18:26 Georg Bege
  2019-04-13 21:34 ` Georg Bege
  0 siblings, 1 reply; 2+ messages in thread
From: Georg Bege @ 2019-04-13 18:26 UTC (permalink / raw)
  To: libffi-discuss

[-- Attachment #1: Type: text/plain, Size: 1917 bytes --]

Hello guys,

Im recently tinkering with PARISC machines which I've left.
I've got two of them, one with HPUX 11iv1 (old, I know) and one with Linux.

According to the libffi main page, HPPA is indeed supported (not on 
Linux, but this is outdated?).
I've written a simple test code, in order to sanity check libffi's basic 
functionality.

This code is working fine on i386 and amd64.. just for reference.
My main goal is getting libffi working (eg. ported) to HPUX LP64... I've 
began consulting the proper documents from HP and learning a bit of 
PARISC asm.. but Im still at the beginning.

Right now, I wanted to confirm the functionality which is obviously 
existing...
The first try I've given is on the C8k with Gentoo Linux:

Linux hppa 4.9.49-gentoo-r1-hppa64 #4 SMP Fri Jun 8 19:33:13 CEST 2018 
parisc64 PA8900 (Shortfin) 9000/785/C8000 GNU/Linux

therion@hppa ~ $ qlist -Iv libffi
dev-libs/libffi-3.2.1
virtual/libffi-3.0.13-r1

So far so good... I've this installation now for a while...
The thing is that my test code is failing with 64bit signed integers.

Im hoping that any of you may look into it, or can lend me a hand - was 
this ever supposed to work? Is it actually working?
My test code is buggy? If so which part? :)

Since it's just test I'll attach my code here.

Output:
---------------snip--------------------
therion@hppa ~ $ ./test-ffi
Signed 8bit integer result:	126
Unsigned 8bit integer result:	254
Signed 16bit integer result:	32766
Unsigned 16bit integer result:	65534
Signed 32bit integer result:	2147483646
Unsigned 32bit integer result:	4294967294
Signed 64bit integer result:	0, expected: 2147483646
test-ffi: test-ffi.c:151: main: Assertion `*src == result' failed.
Aborted
---------------snip--------------------

best regards,
-- 
Georg Bege
Mail: georg@bege.email
XMPP: therion@ninth-art.de
IRC: megaTherion @ Freenode

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: test-ffi.c --]
[-- Type: text/x-csrc; name="test-ffi.c", Size: 6672 bytes --]

/**
 * libffi C99 test code
 * - proves that libffi calls are working correctly
 * copyright (C) 2019 <georg@bege.email>
 * Created on:	12th April 2019
 * Modified on:	13th April 2019
 */
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <assert.h>
#include <ffi.h>
#include <inttypes.h>
#include <float.h>

typedef void (*ffi_callback)(void);

typedef struct {
	int _1;
	int _2;
} simple_t;

/* adder functors */
int8_t		add_signed8(int8_t a, int8_t b)			{ return a + b; }
uint8_t 	add_unsigned8(uint8_t a, uint8_t b)		{ return a + b; }
int16_t 	add_signed16(int16_t a, int16_t b)		{ return a + b; }
uint16_t	add_unsigned16(uint16_t a, uint16_t b)	{ return a + b; }
int32_t 	add_signed32(int32_t a, int32_t b)		{ return a + b; }
uint32_t 	add_unsigned32(uint32_t a, uint32_t b)	{ return a + b; }
int64_t 	add_signed64(int64_t a, int64_t b)		{ return a + b; }
uint64_t 	add_unsigned64(uint64_t a, uint64_t b)	{ return a + b; }
float		add_floatS(float a, float b)			{ return a + b; }
double		add_floatD(double a, double b)			{ return a + b; }

simple_t	add_simple(simple_t a, simple_t b) {
	simple_t ret = { a._1 + b._1, a._2 + b._2 };
	return ret;
}

/* ffi proxy function */
ffi_arg call(ffi_type **args, void **values, ffi_type *retarg,
			 size_t len, ffi_callback func)
{
	ffi_cif cif;
	ffi_arg rc;
	
	/* Iniitalize the cif */
	int ret = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, len, retarg, args);
	if(ret != FFI_OK) {
		fprintf(stderr, "[%s] Cant prepare ffi context: %d\n", __func__, ret);
		exit(EXIT_FAILURE);
	}
	
	ffi_call(&cif, func, &rc, values);
	return rc;
}

int main(void) {
	ffi_cif cif;

	/* 8bit signed integer test */
	{
		int8_t a = (CHAR_MAX / 2) + 1, b = (CHAR_MAX / 2) - 1;
		const int8_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_sint8, &ffi_type_sint8};
		void *values[] = {&a, &b};
		
		ffi_arg rc = call(args, values, &ffi_type_sint8, 2, (ffi_callback)add_signed8);
		printf("Signed 8bit integer result:\t%"PRIi8"\n", (int8_t)rc);
		assert( (int8_t)rc == result );
	}
	
	/* 8bit unsigned integer test */
	{
		uint8_t a = (UCHAR_MAX / 2) + 1, b = (UCHAR_MAX / 2) - 1;
		const uint8_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint8, &ffi_type_uint8};
		void *values[] = {&a, &b};
		
		ffi_arg rc = call(args, values, &ffi_type_uint8, 2, (ffi_callback)add_unsigned8);
		printf("Unsigned 8bit integer result:\t%"PRIu8"\n", (uint8_t)rc);
		assert( (uint8_t)rc == result);
	}
	
	/* 16bit signed integer test */
	{
		int16_t a = (SHRT_MAX / 2) + 1, b = (SHRT_MAX / 2) - 1;
		const int16_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_sint16, &ffi_type_sint16};
		void *values[] = {&a, &b};
		
		ffi_arg rc = call(args, values, &ffi_type_sint16, 2, (ffi_callback)add_signed16);
		printf("Signed 16bit integer result:\t%"PRIi16"\n", (int16_t)rc);
		assert( (int16_t)rc == result );
	}
	
	/* 16bit unsigned integer test */
	{
		uint16_t a = (USHRT_MAX / 2) + 1, b = (USHRT_MAX / 2) - 1;
		const uint16_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint16, &ffi_type_uint16};
		void *values[] = {&a, &b};
		
		ffi_arg rc = call(args, values, &ffi_type_uint16, 2, (ffi_callback)add_unsigned16);
		printf("Unsigned 16bit integer result:\t%"PRIu16"\n", (uint16_t)rc);
		assert( (uint16_t)rc == result );
	}
	
	/* 32bit signed integer test */
	{
		int32_t a = (INT_MAX / 2) + 1, b = (INT_MAX / 2) - 1;
		const int32_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_sint32, &ffi_type_sint32};
		void *values[] = {&a, &b};
	
		ffi_arg rc = call(args, values, &ffi_type_sint32, 2, (ffi_callback)add_signed32);
		printf("Signed 32bit integer result:\t%"PRIi32"\n", (int32_t)rc);
		assert( (int32_t)rc == result );
	}
	
	/* 32bit unsigned integer test */
	{
		uint32_t a = (UINT_MAX / 2) + 1, b = (UINT_MAX / 2) - 1;
		const uint32_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint32, &ffi_type_uint32};
		void *values[] = {&a, &b};
		
		ffi_arg rc = call(args, values, &ffi_type_uint32, 2, (ffi_callback)add_unsigned32);
		printf("Unsigned 32bit integer result:\t%"PRIu32"\n", (uint32_t)rc);
		assert( (uint32_t)rc == result );
	}
	
	/* 64bit signed integer test */
	{
		int64_t a = (LONG_MAX / 2) + 1, b = (LONG_MAX / 2) - 1;
		const int64_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_sint64, &ffi_type_sint64};
		void *values[] = {&a, &b};
		
		ffi_arg rc = call(args, values, &ffi_type_sint64, 2, (ffi_callback)add_signed64);
		const int64_t *src = (int64_t*)&rc;
		
		printf("Signed 64bit integer result:\t%"PRIi64", expected: %"PRIi64"\n", *src, result);
		assert( *src == result );
	}
	
	/* 64bit unsigned integer test */
	{
		uint64_t a = (ULONG_MAX / 2) + 1, b = (ULONG_MAX / 2) - 1;
		const uint64_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint64, &ffi_type_uint64};
		void *values[] = {&a, &b};
		
		ffi_arg rc = call(args, values, &ffi_type_uint64, 2, (ffi_callback)add_unsigned64);
		const uint64_t *urc = (uint64_t*)&rc;
		
		printf("Unsigned 64bit integer result:\t%"PRIu64"\n", *urc);
		assert( *urc == result );
	}
	
	/* single precision float test */
	{
		float a = (FLT_MAX / 2.0F) + 0.5F, b = (FLT_MAX / 2.0F) - 0.5F;
		const float result = a + b;
		
		ffi_type *args[] = {&ffi_type_float, &ffi_type_float};
		void *values[] = {&a, &b};
		
		ffi_arg rc = call(args, values, &ffi_type_float, 2, (ffi_callback)add_floatS);
		const float *frc = (float*)&rc;
		
		printf("Single precision float result:\t%f\n", *frc);
		assert( *frc == result );
	}
	
	/* double precision float test */
	{
		double a = (DBL_MAX / 2.0) + 0.5, b = (DBL_MAX / 2.0) - 0.5;
		const double result = a + b;
		
		ffi_type *args[] = {&ffi_type_double, &ffi_type_double};
		void *values[] = {&a, &b};
		
		ffi_arg rc = call(args, values, &ffi_type_double, 2, (ffi_callback)add_floatD);
		const double *frc = (double*)&rc;
		
		printf("Double precision float result:\t%lf\n", *frc);
		assert( *frc == result );
	}
	
#if 0
	/* struct test */
	{
		simple_t a = {(INT_MAX / 2) + 1, (INT_MAX / 2) - 1};
		simple_t b = {(INT_MAX / 2) - 1, (INT_MAX / 2) + 1};
		const simple_t result = {a._1 + b._1, a._2 + b._2};
		
		ffi_type *args[] = {&ffi_type_pointer, &ffi_type_pointer};
		void *values[] = {&a, &b};
		
		ffi_arg rc = call(args, values, &ffi_type_pointer, 2, (ffi_callback)add_simple);
		const simple_t *src = (simple_t*)&rc;
		
		printf("Simple_t result:\t%d, %d\n", src->_1, src->_2);
		assert( src->_1 == result._1 && src->_2 == result._2 );
	}
#endif
	
	exit(EXIT_SUCCESS);
}

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: libffi on the HPPA (parisc)
  2019-04-13 18:26 libffi on the HPPA (parisc) Georg Bege
@ 2019-04-13 21:34 ` Georg Bege
  0 siblings, 0 replies; 2+ messages in thread
From: Georg Bege @ 2019-04-13 21:34 UTC (permalink / raw)
  To: libffi-discuss

[-- Attachment #1: Type: text/plain, Size: 2552 bytes --]

Hi again,

Ok I think I've found my mistake - the rc type wasnt large enough to 
hold 64bit of data.
ffi_arg seems to be 32bit on 32bit systems.. should have known, I fixed 
my code accordingly.

I also fixed my bug regarding custom struct handling, it works now on 
multiple arch's (i386, amd64, parisc, arm). :)

However, feel free to pass along helpful advice regarding my testing 
code and/or regarding porting libffi to parisc64.

Am 13.04.19 um 20:26 schrieb Georg Bege:
> Hello guys,
> 
> Im recently tinkering with PARISC machines which I've left.
> I've got two of them, one with HPUX 11iv1 (old, I know) and one with Linux.
> 
> According to the libffi main page, HPPA is indeed supported (not on 
> Linux, but this is outdated?).
> I've written a simple test code, in order to sanity check libffi's basic 
> functionality.
> 
> This code is working fine on i386 and amd64.. just for reference.
> My main goal is getting libffi working (eg. ported) to HPUX LP64... I've 
> began consulting the proper documents from HP and learning a bit of 
> PARISC asm.. but Im still at the beginning.
> 
> Right now, I wanted to confirm the functionality which is obviously 
> existing...
> The first try I've given is on the C8k with Gentoo Linux:
> 
> Linux hppa 4.9.49-gentoo-r1-hppa64 #4 SMP Fri Jun 8 19:33:13 CEST 2018 
> parisc64 PA8900 (Shortfin) 9000/785/C8000 GNU/Linux
> 
> therion@hppa ~ $ qlist -Iv libffi
> dev-libs/libffi-3.2.1
> virtual/libffi-3.0.13-r1
> 
> So far so good... I've this installation now for a while...
> The thing is that my test code is failing with 64bit signed integers.
> 
> Im hoping that any of you may look into it, or can lend me a hand - was 
> this ever supposed to work? Is it actually working?
> My test code is buggy? If so which part? :)
> 
> Since it's just test I'll attach my code here.
> 
> Output:
> ---------------snip--------------------
> therion@hppa ~ $ ./test-ffi
> Signed 8bit integer result:    126
> Unsigned 8bit integer result:    254
> Signed 16bit integer result:    32766
> Unsigned 16bit integer result:    65534
> Signed 32bit integer result:    2147483646
> Unsigned 32bit integer result:    4294967294
> Signed 64bit integer result:    0, expected: 2147483646
> test-ffi: test-ffi.c:151: main: Assertion `*src == result' failed.
> Aborted
> ---------------snip--------------------
> 
> best regards,

-- 
Georg Bege
Mail: georg@bege.email
XMPP: therion@ninth-art.de
IRC: megaTherion @ Freenode

[-- Attachment #2: test-ffi.c --]
[-- Type: text/x-csrc, Size: 6496 bytes --]

/**
 * libffi C99 test code
 * - proves that libffi calls are working correctly
 * copyright (C) 2019 <georg@bege.email>
 * Created on:	12th April 2019
 * Modified on:	13th April 2019
 */
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <assert.h>
#include <ffi.h>
#include <inttypes.h>
#include <float.h>

typedef void (*ffi_callback)(void);

typedef struct {
	int _1;
	int _2;
} simple_t;

/* adder functors */
int8_t		add_signed8(int8_t a, int8_t b)			{ return a + b; }
uint8_t 	add_unsigned8(uint8_t a, uint8_t b)		{ return a + b; }
int16_t 	add_signed16(int16_t a, int16_t b)		{ return a + b; }
uint16_t	add_unsigned16(uint16_t a, uint16_t b)	{ return a + b; }
int32_t 	add_signed32(int32_t a, int32_t b)		{ return a + b; }
uint32_t 	add_unsigned32(uint32_t a, uint32_t b)	{ return a + b; }
int64_t 	add_signed64(int64_t a, int64_t b)		{ return a + b; }
uint64_t 	add_unsigned64(uint64_t a, uint64_t b)	{ return a + b; }
float		add_floatS(float a, float b)			{ return a + b; }
double		add_floatD(double a, double b)			{ return a + b; }

simple_t	add_simple(simple_t a, simple_t b) {
	simple_t ret = { a._1 + b._1, a._2 + b._2 };
	return ret;
}

/* ffi proxy function */
ffi_arg call(ffi_type **args, void **values, size_t nargs,
		ffi_type rctype, ffi_callback func)
{
	ffi_cif cif;
	ffi_arg rc;
	
	/* Iniitalize the cif */
	int ret = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, nargs, &rctype, args);
	if(ret != FFI_OK) {
		fprintf(stderr, "[%s] Cant prepare ffi context: %d\n", __func__, ret);
		exit(EXIT_FAILURE);
	}
	
	ffi_call(&cif, func, &rc, values);
	return rc;
}

void call_ext(ffi_type **args, void **values, size_t nargs,
				ffi_type rctype, void *rc, ffi_callback func)
{
	ffi_cif cif;
	
	/* Iniitalize the cif */
	int ret = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, nargs, &rctype, args);
	if(ret != FFI_OK) {
		fprintf(stderr, "[%s] Cant prepare ffi context: %d\n", __func__, ret);
		exit(EXIT_FAILURE);
	}
	
	ffi_call(&cif, func, rc, values);
}

int main(void) {
	/* 8bit signed integer test */
	{
		int8_t a = (SCHAR_MAX / 2) + 1, b = (SCHAR_MAX / 2) - 1;
		const int8_t result = a + b;
	
		ffi_type *args[] = {&ffi_type_sint8, &ffi_type_sint8};
		void *values[] = {&a, &b};
		
		int8_t rc = (int8_t)call(args, values, 2, ffi_type_sint8, (ffi_callback)add_signed8);
		printf("Signed 8bit integer result:\t%"PRIi8"\n", rc);
		assert(rc == result);
	}

	/* 8bit unsigned integer test */
	{
		uint8_t a = (UCHAR_MAX / 2) + 1, b = (UCHAR_MAX / 2) - 1;
		const uint8_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint8, &ffi_type_uint8};
		void *values[] = {&a, &b};
		
		uint8_t rc = call(args, values, 2, ffi_type_uint8, (ffi_callback)add_unsigned8);
		printf("Unsigned 8bit integer result:\t%"PRIu8"\n", rc);
		assert(rc == result);
	}

	/* 16bit signed integer test */
	{
		int16_t a = (SHRT_MAX / 2) + 1, b = (SHRT_MAX / 2) - 1;
		const int16_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_sint16, &ffi_type_sint16};
		void *values[] = {&a, &b};
		
		int16_t rc = call(args, values, 2, ffi_type_sint16, (ffi_callback)add_signed16);
		printf("Signed 16bit integer result:\t%"PRIi16"\n", rc);
		assert(rc == result);
	}

	/* 16bit unsigned integer test */
	{
		uint16_t a = (USHRT_MAX / 2) + 1, b = (USHRT_MAX / 2) - 1;
		const uint16_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint16, &ffi_type_uint16};
		void *values[] = {&a, &b};
		
		uint16_t rc = call(args, values, 2, ffi_type_uint16, (ffi_callback)add_unsigned16);
		printf("Unsigned 16bit integer result:\t%"PRIu16"\n", rc);
		assert(rc == result);
	}

	/* 32bit signed integer test */
	{
		int32_t a = (INT_MAX / 2) + 1, b = (INT_MAX / 2) - 1;
		const int32_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_sint32, &ffi_type_sint32};
		void *values[] = {&a, &b};
	
		int32_t rc = call(args, values, 2, ffi_type_sint32, (ffi_callback)add_signed32);
		printf("Signed 32bit integer result:\t%"PRIi32"\n", rc);
		assert(rc == result);
	}

	/* 32bit unsigned integer test */
	{
		uint32_t a = (UINT_MAX / 2) + 1, b = (UINT_MAX / 2) - 1;
		const uint32_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint32, &ffi_type_uint32};
		void *values[] = {&a, &b};
		
		uint32_t rc = call(args, values, 2, ffi_type_uint32, (ffi_callback)add_unsigned32);
		printf("Unsigned 32bit integer result:\t%"PRIu32"\n", rc);
		assert(rc == result);
	}

	/* 64bit signed integer test */
	{
		int64_t a = (LONG_MAX / 2) + 1, b = (LONG_MAX / 2) - 1, rc;
		const int64_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_sint64, &ffi_type_sint64};
		void *values[] = {&a, &b};
		
		call_ext(args, values, 2, ffi_type_sint64, &rc, (ffi_callback)add_signed64);
		printf("Signed 64bit integer result:\t%"PRIi64"\n", rc);
		assert(rc == result);
	}

	/* 64bit unsigned integer test */
	{
		uint64_t a = (ULONG_MAX / 2) + 1, b = (ULONG_MAX / 2) - 1, rc;
		const uint64_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint64, &ffi_type_uint64};
		void *values[] = {&a, &b};
		
		call_ext(args, values, 2, ffi_type_uint64, &rc, (ffi_callback)add_unsigned64);
		printf("Unsigned 64bit integer result:\t%"PRIu64"\n", rc);
		assert(rc == result);
	}

	/* single precision float test */
	{
		float a = (FLT_MAX / 2.0F) + 0.5F, b = (FLT_MAX / 2.0F) - 0.5F, rc;
		const float result = a + b;
		
		ffi_type *args[] = {&ffi_type_float, &ffi_type_float};
		void *values[] = {&a, &b};
		
		call_ext(args, values, 2, ffi_type_float, &rc, (ffi_callback)add_floatS);
		printf("Single precision float result:\t%f\n", rc);
		assert(rc == result);
	}

	/* double precision float test */
	{
		double a = (DBL_MAX / 2.0) + 0.5, b = (DBL_MAX / 2.0) - 0.5, rc;
		const double result = a + b;
		
		ffi_type *args[] = {&ffi_type_double, &ffi_type_double};
		void *values[] = {&a, &b};
		
		call_ext(args, values, 2, ffi_type_double, &rc, (ffi_callback)add_floatD);
		printf("Double precision float result:\t%lf\n", rc);
		assert(rc == result);
	}

	/* struct test */
	{
		simple_t a = {(INT_MAX / 2) + 1, (INT_MAX / 2) - 1};
		simple_t b = {(INT_MAX / 2) - 1, (INT_MAX / 2) + 1}, rc;
		const simple_t result = {a._1 + b._1, a._2 + b._2};
		
		ffi_type *prim[] = {&ffi_type_sint32, &ffi_type_sint32, NULL};
		ffi_type sc = {0, 0, FFI_TYPE_STRUCT, (ffi_type**)&prim};
		ffi_type *args[] = {&sc, &sc};
		void *values[] = {&a, &b};
		
		call_ext(args, values, 2, sc, &rc, (ffi_callback)add_simple);
		printf("Simple_t result:\t%d, %d\n", rc._1, rc._2);
		assert(rc._1 == result._1 && rc._2 == result._2);
	}
	
	exit(EXIT_SUCCESS);
}

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2019-04-13 21:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-13 18:26 libffi on the HPPA (parisc) Georg Bege
2019-04-13 21:34 ` Georg Bege

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).