/*
 * Test code generation for 64-bit shifts by a constant amount
 *
 * -O0: ASL fails from 32-62 (using Maverick cfsh64 insns)
 * -O1: ASR fails from 33-63 (using Maverick cfsh64 insns)
 */

#include <stdio.h>
#include <stdlib.h>

typedef unsigned long long ui64;
typedef long long i64;

#define UI64 ((ui64) 0xdeadb0d101234567ULL)
#define I64 ((i64) 0xdeadb0d101234567LL)

extern uitest(ui64 v);
extern itest(i64 v);

main()
{
	int i;
	for (i=1000000; i!=0; i--) {
		uitest(UI64);
		itest(I64);
	}

	exit(0);
}

ui64 left[65] = {
	UI64 << 0, UI64 << 1, UI64 << 2, UI64 << 3, UI64 << 4,
	UI64 << 5, UI64 << 6, UI64 << 7, UI64 << 8, UI64 << 9,
	UI64 << 10, UI64 << 11, UI64 << 12, UI64 << 13, UI64 << 14,
	UI64 << 15, UI64 << 16, UI64 << 17, UI64 << 18, UI64 << 19,
	UI64 << 20, UI64 << 21, UI64 << 22, UI64 << 23, UI64 << 24,
	UI64 << 25, UI64 << 26, UI64 << 27, UI64 << 28, UI64 << 29,
	UI64 << 30, UI64 << 31, UI64 << 32, UI64 << 33, UI64 << 34,
	UI64 << 35, UI64 << 36, UI64 << 37, UI64 << 38, UI64 << 39,
	UI64 << 40, UI64 << 41, UI64 << 42, UI64 << 43, UI64 << 44,
	UI64 << 45, UI64 << 46, UI64 << 47, UI64 << 48, UI64 << 49,
	UI64 << 50, UI64 << 51, UI64 << 52, UI64 << 53, UI64 << 54,
	UI64 << 55, UI64 << 56, UI64 << 57, UI64 << 58, UI64 << 59,
	UI64 << 60, UI64 << 61, UI64 << 62, UI64 << 63, UI64 << 64,
};

ui64 lright[65] = {
	UI64 >> 0, UI64 >> 1, UI64 >> 2, UI64 >> 3, UI64 >> 4,
	UI64 >> 5, UI64 >> 6, UI64 >> 7, UI64 >> 8, UI64 >> 9,
	UI64 >> 10, UI64 >> 11, UI64 >> 12, UI64 >> 13, UI64 >> 14,
	UI64 >> 15, UI64 >> 16, UI64 >> 17, UI64 >> 18, UI64 >> 19,
	UI64 >> 20, UI64 >> 21, UI64 >> 22, UI64 >> 23, UI64 >> 24,
	UI64 >> 25, UI64 >> 26, UI64 >> 27, UI64 >> 28, UI64 >> 29,
	UI64 >> 30, UI64 >> 31, UI64 >> 32, UI64 >> 33, UI64 >> 34,
	UI64 >> 35, UI64 >> 36, UI64 >> 37, UI64 >> 38, UI64 >> 39,
	UI64 >> 40, UI64 >> 41, UI64 >> 42, UI64 >> 43, UI64 >> 44,
	UI64 >> 45, UI64 >> 46, UI64 >> 47, UI64 >> 48, UI64 >> 49,
	UI64 >> 50, UI64 >> 51, UI64 >> 52, UI64 >> 53, UI64 >> 54,
	UI64 >> 55, UI64 >> 56, UI64 >> 57, UI64 >> 58, UI64 >> 59,
	UI64 >> 60, UI64 >> 61, UI64 >> 62, UI64 >> 63, UI64 >> 64,
};

i64 aright[65] = {
	I64 >> 0, I64 >> 1, I64 >> 2, I64 >> 3, I64 >> 4,
	I64 >> 5, I64 >> 6, I64 >> 7, I64 >> 8, I64 >> 9,
	I64 >> 10, I64 >> 11, I64 >> 12, I64 >> 13, I64 >> 14,
	I64 >> 15, I64 >> 16, I64 >> 17, I64 >> 18, I64 >> 19,
	I64 >> 20, I64 >> 21, I64 >> 22, I64 >> 23, I64 >> 24,
	I64 >> 25, I64 >> 26, I64 >> 27, I64 >> 28, I64 >> 29,
	I64 >> 30, I64 >> 31, I64 >> 32, I64 >> 33, I64 >> 34,
	I64 >> 35, I64 >> 36, I64 >> 37, I64 >> 38, I64 >> 39,
	I64 >> 40, I64 >> 41, I64 >> 42, I64 >> 43, I64 >> 44,
	I64 >> 45, I64 >> 46, I64 >> 47, I64 >> 48, I64 >> 49,
	I64 >> 50, I64 >> 51, I64 >> 52, I64 >> 53, I64 >> 54,
	I64 >> 55, I64 >> 56, I64 >> 57, I64 >> 58, I64 >> 59,
	I64 >> 60, I64 >> 61, I64 >> 62, I64 >> 63, I64 >> 64,
};

/* test logical shifts by a constant */
uitest(ui64 va)
{
	register int i = -1;
	char *s = "ASL failed at %02d: 0x%016llx 0x%016llx\n";
	register ui64 v asm("mvdx8") = va;

#define DO(N) if (v << N != left[++i]) printf(s, i, left[i], v << N)
	DO(0); DO(1); DO(2); DO(3); DO(4);
	DO(5); DO(6); DO(7); DO(8); DO(9);
	DO(10); DO(11); DO(12); DO(13); DO(14);
	DO(15); DO(16); DO(17); DO(18); DO(19);
	DO(20); DO(21); DO(22); DO(23); DO(24);
	DO(25); DO(26); DO(27); DO(28); DO(29);
	DO(30); DO(31); DO(32); DO(33); DO(34);
	DO(35); DO(36); DO(37); DO(38); DO(39);
	DO(40); DO(41); DO(42); DO(43); DO(44);
	DO(45); DO(46); DO(47); DO(48); DO(49);
	DO(50); DO(51); DO(52); DO(53); DO(54);
	DO(55); DO(56); DO(57); DO(58); DO(59);
	DO(60); DO(61); DO(62); DO(63); DO(64);
#undef DO

	i = -1; s = "LSR failed at %02d: 0x%016llx 0x%016llx\n";
#define DO(N) if (v >> N != lright[++i]) printf(s, i, lright[i], v >> N)
	DO(0); DO(1); DO(2); DO(3); DO(4);
	DO(5); DO(6); DO(7); DO(8); DO(9);
	DO(10); DO(11); DO(12); DO(13); DO(14);
	DO(15); DO(16); DO(17); DO(18); DO(19);
	DO(20); DO(21); DO(22); DO(23); DO(24);
	DO(25); DO(26); DO(27); DO(28); DO(29);
	DO(30); DO(31); DO(32); DO(33); DO(34);
	DO(35); DO(36); DO(37); DO(38); DO(39);
	DO(40); DO(41); DO(42); DO(43); DO(44);
	DO(45); DO(46); DO(47); DO(48); DO(49);
	DO(50); DO(51); DO(52); DO(53); DO(54);
	DO(55); DO(56); DO(57); DO(58); DO(59);
	DO(60); DO(61); DO(62); DO(63); DO(64);
#undef DO
}

/* test arithmetic shifts by a constant */
itest(i64 va)
{
	register int i = -1;
	char *s = "ASR failed at %02d: 0x%016llx 0x%016llx\n";
	register i64 v asm("mvdx8") = va;

#define DO(N) if (v >> N != aright[++i]) printf(s, i, aright[i], v >> N)
	DO(0); DO(1); DO(2); DO(3); DO(4);
	DO(5); DO(6); DO(7); DO(8); DO(9);
	DO(10); DO(11); DO(12); DO(13); DO(14);
	DO(15); DO(16); DO(17); DO(18); DO(19);
	DO(20); DO(21); DO(22); DO(23); DO(24);
	DO(25); DO(26); DO(27); DO(28); DO(29);
	DO(30); DO(31); DO(32); DO(33); DO(34);
	DO(35); DO(36); DO(37); DO(38); DO(39);
	DO(40); DO(41); DO(42); DO(43); DO(44);
	DO(45); DO(46); DO(47); DO(48); DO(49);
	DO(50); DO(51); DO(52); DO(53); DO(54);
	DO(55); DO(56); DO(57); DO(58); DO(59);
	DO(60); DO(61); DO(62); DO(63); DO(64);
#undef DO
}
