#include <stddef.h>
#include <stdio.h>


#ifndef PG_ALIGN_128
#define PG_ALIGN_128 8
#endif

/* GCC, Sunpro and XLC support aligned */
#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
#define pg_attribute_aligned(a) __attribute__((aligned(a)))
#endif

typedef __int128 int128a
#if defined(pg_attribute_aligned)
pg_attribute_aligned(PG_ALIGN_128)
#endif
;

/*
 * These are globals to discourage the compiler from folding all the
 * arithmetic tests down to compile-time constants.  We do not have
 * convenient support for 128bit literals at this point...
 */
struct glob128
{
	__int128	start;
	char		pad;
	int128a		a;
	int128a		b;
	int128a		c;
	int128a		d;
} g = {0, 'p', 48828125, 97656250, 0, 0};

int128a holder;

void pass_by_val(char *buffer, int128a par) {
   holder = par;
}

int
main()
{
	char *message = "Everything is fine";
	short int i16 = 31000;
	unsigned short int u16 = 49000;
	int i32 = 48828125;
	long int i64 = 97656225L << 12;
	int128a q;
	int failures = 0;

	/* Basic arithmetic tests */

	g.a = (g.a << 12) + 1;		/* 200000000001 */
	g.b = (g.b << 12) + 5;		/* 400000000005 */
	/* use the most relevant arithmetic ops */
	g.c = g.a * g.b;
	g.d = (g.c + g.b) / g.b;
	/* return different values, to prevent optimizations */
	if (g.d != g.a + 1)
	{
		printf("wrong arithmetic result\n");
		failures++;
	}
	else
	{
		printf("basic aritmetic OK\n");
	}

	pass_by_val(message, (int128a) i16);
	q = (int128a) i16;
	printf("pass int 16 %s\n", (q == holder) ? "OK" : "FAILED");
	if (q != holder)
		failures++;

	pass_by_val(message, (int128a) u16);
	q = (int128a) u16;
	printf("pass uint 16 %s\n", (q == holder) ? "OK" : "FAILED");
	if (q != holder)
		failures++;

	pass_by_val(message, (int128a) i32);
	q = (int128a) i32;
	printf("pass int 32 %s\n", (q == holder) ? "OK" : "FAILED");
	if (q != holder)
		failures++;

	pass_by_val(message, (int128a) i64);
	q = (int128a) i64;
	printf("pass int 64 %s\n", (q == holder) ? "OK" : "FAILED");
	if (q != holder)
		failures++;

	q = (int128a) (i64 << 33);
	pass_by_val(message, q);
	printf("pass int 128 %s\n", (q == holder) ? "OK" : "FAILED");
	if (q != holder)
		failures++;

	return failures;
}
